審計
基礎知識
Spring Data 提供精妙的支援,可以透明地跟蹤誰建立或更改了實體以及何時發生了更改。為了利用此功能,您需要為您的實體類配備審計元資料,這些元資料可以透過使用註解或實現介面來定義。此外,必須透過註解配置或 XML 配置啟用審計功能,以註冊所需的基礎設施元件。有關配置示例,請參閱針對特定儲存的部分。
僅跟蹤建立日期和修改日期的應用程式不需要讓其實體實現 |
基於註解的審計元資料
我們提供了 @CreatedBy
和 @LastModifiedBy
用來捕獲建立或修改實體的使用者,以及 @CreatedDate
和 @LastModifiedDate
用來捕獲更改發生的時間。
class Customer {
@CreatedBy
private User user;
@CreatedDate
private Instant createdDate;
// … further properties omitted
}
如您所見,可以根據您想要捕獲的資訊有選擇地應用這些註解。指示捕獲更改發生時間的註解可以用於以下型別的屬性:JDK8 日期和時間型別、long
、Long
,以及傳統的 Java Date
和 Calendar
。
審計元資料不一定需要位於根級實體中,但可以新增到嵌入式實體中(取決於實際使用的儲存),如下面的程式碼片段所示。
class Customer {
private AuditMetadata auditingMetadata;
// … further properties omitted
}
class AuditMetadata {
@CreatedBy
private User user;
@CreatedDate
private Instant createdDate;
}
基於介面的審計元資料
如果您不想使用註解來定義審計元資料,可以使您的域類實現 Auditable
介面。它暴露了所有審計屬性的 setter 方法。
AuditorAware
如果您使用了 @CreatedBy
或 @LastModifiedBy
,審計基礎設施需要某種方式感知當前的主體(principal)。為此,我們提供了 AuditorAware<T>
SPI 介面,您必須實現該介面來告訴基礎設施當前與應用程式互動的使用者或系統是誰。泛型型別 T
定義了使用 @CreatedBy
或 @LastModifiedBy
註解的屬性必須是什麼型別。
以下示例展示了一個使用 Spring Security 的 Authentication
物件的介面實現:
class SpringSecurityAuditorAware implements AuditorAware<User> {
@Override
public Optional<User> getCurrentAuditor() {
return Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
該實現訪問由 Spring Security 提供的 Authentication
物件,並查詢您在 UserDetailsService
實現中建立的自定義 UserDetails
例項。我們在這裡假設您透過 UserDetails
實現暴露了域使用者,但根據找到的 Authentication
,您也可以從任何地方查詢它。
ReactiveAuditorAware
使用響應式基礎設施時,您可能希望利用上下文資訊來提供 @CreatedBy
或 @LastModifiedBy
資訊。我們提供了 ReactiveAuditorAware<T>
SPI 介面,您必須實現該介面來告訴基礎設施當前與應用程式互動的使用者或系統是誰。泛型型別 T
定義了使用 @CreatedBy
或 @LastModifiedBy
註解的屬性必須是什麼型別。
以下示例展示了一個使用響應式 Spring Security 的 Authentication
物件的介面實現:
class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {
@Override
public Mono<User> getCurrentAuditor() {
return ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(User.class::cast);
}
}
該實現訪問由 Spring Security 提供的 Authentication
物件,並查詢您在 UserDetailsService
實現中建立的自定義 UserDetails
例項。我們在這裡假設您透過 UserDetails
實現暴露了域使用者,但根據找到的 Authentication
,您也可以從任何地方查詢它。