使用SpringBoot2和SpringDataJPA實現審計
在本文中,我們將討論如何配置JPA以自動持久儲存任何實體的CreatedBy,CreatedDate,LastModifiedBy和LastModifiedDate標註的欄位列。我們將建立一個簡單的Spring Boot CRUD REST API,並使用spring資料JPA實現審計。
在任何業務應用程式中,審計意味著跟蹤和記錄我們在持久記錄中所做的每一項更改,這意味著跟蹤每個插入,更新和刪除操作並存儲它。審計有助於我們維護歷史記錄,以後可以幫助我們跟蹤使用者作業系統的活動。
這樣就不需要在每次儲存,更新或刪除操作上進行手動編寫程式碼,我們完全可以使用第三方庫自動執行。Spring Data提供了複雜的支援,可以透明地跟蹤建立或更改實體的人員以及發生這種情況的時間點。
首先必須為實體類配備審計元資料,該元資料可以使用註釋或通過實現介面來定義。在此示例中,我們將使用審計欄位建立一個通用的通用Auditable抽象類,以便任何實體都可以擴充套件它以使用審計。
直接使用JPA依賴即可:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
使用Spring資料註釋建立通用可審計類@CreatedBy,@ CreatedDate,@ LastModifiedBy和@LastModifiedDate:
@MappedSuperclass @EntityListeners(AuditingEntityListener.class) public abstract class Auditable<U> { @CreatedBy protected U createdBy; @CreatedDate @Temporal(TIMESTAMP) protected Date createdDate; @LastModifiedBy protected U lastModifiedBy; @LastModifiedDate @Temporal(TIMESTAMP) protected Date lastModifiedDate; public U getCreatedBy() { return createdBy; } public void setCreatedBy(U createdBy) { this.createdBy = createdBy; } public Date getCreatedDate() { return createdDate; } public void setCreatedDate(Date createdDate) { this.createdDate = createdDate; } public U getLastModifiedBy() { return lastModifiedBy; } public void setLastModifiedBy(U lastModifiedBy) { this.lastModifiedBy = lastModifiedBy; } public Date getLastModifiedDate() { return lastModifiedDate; } public void setLastModifiedDate(Date lastModifiedDate) { this.lastModifiedDate = lastModifiedDate; } }
讓我們理解重要的JPA稽核註釋:
-
@CreatedDate - 宣告一個欄位,表示建立包含該欄位的實體的日期。
-
@LastModifiedDate - 宣告一個欄位,表示最近修改了包含該欄位的實體的日期。
-
@CreatedBy - 宣告一個欄位,表示建立包含該欄位的實體的主體。
-
@LastModifiedBy - 宣告一個欄位,表示最近修改包含該欄位的實體的主體。
使用帶有@EntityListeners的AuditingEntityListener類,Spring Data JPA提供了一個JPA實體監聽器類AuditingEntityListener ,它包含回撥方法(使用@PrePersist 和@PreUpdate 註釋),當我們將持久化或更新我們的實體時,它將用於持久化和更新這些屬性。
JPA提供了@EntityListeners 註釋來指定回撥監聽器類,我們用它來註冊我們的AuditingEntityListener 類。
JPA可以使用當前系統時間分析createdDate和lastModifiedDate,但是createdBy和lastModifiedBy欄位呢?JPA將如何識別儲存在其中的內容?
要告訴JPA當前登入的使用者,我們需要提供AuditorAware的實現並覆蓋getCurrentAuditor()方法。在getCurrentAuditor()中,我們需要獲取當前登入的使用者。
提供了一個硬編碼使用者,但是如果你使用的是Spring Security,則可用它來查詢當前登入的使用者。
public class AuditorAwareImpl implements AuditorAware<String> { @Override public Optional<String> getCurrentAuditor() { return Optional.of("Ramesh"); // Use below commented code when will use Spring Security. } } // ------------------ Use below code for spring security -------------------------- /*class SpringSecurityAuditorAware implements AuditorAware<User> { public User getCurrentAuditor() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null || !authentication.isAuthenticated()) { return null; } return ((MyUserDetails) authentication.getPrincipal()).getUser(); } }*/
現在,我們可以建立一個業務JPA實體繼承上面Auditable類:
@Entity @Table(name = "users") @EntityListeners(AuditingEntityListener.class) public class User extends Auditable<String> { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Column(name = "first_name", nullable = false) private String firstName; @Column(name = "last_name", nullable = false) private String lastName; @Column(name = "email_address", nullable = false) private String emailId; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmailId() { return emailId; } public void setEmailId(String emailId) { this.emailId = emailId; } }
指定@EnableJpaAuditing 來啟用JPA審計:
@SpringBootApplication @EnableJpaAuditing(auditorAwareRef = "auditorAware") public class Springboot2JpaAuditingApplication { @Bean public AuditorAware<String> auditorAware() { return new AuditorAwareImpl(); } public static void main(String[] args) { SpringApplication.run(Springboot2JpaAuditingApplication.class, args); } }
現在,我們完成了所有JPA審計的主要設定。
ofollow,noindex" target="_blank">原始碼連線Github