Spring @Audited 审计——‘createdBy’,‘createdDate’,‘lastModifiedBy’和‘lastModifiedDate’

原创性声明:本文完全为笔者原创,请尊重笔者劳动力。转载务必注明原文地址。

这是一个很常见的需求 :

例如。数据库中,文章表(articles)中的某条记录是被那个账号创建的(@CreateBy),最后的一次更新是哪个账号干的(@LastModifiedBy),以及创建的时间是什么(@CreateDate),最后更新的时间又是什么(@LastModifiedDate)?

这既可以作为用户所需要的字段信息,在一定程度上也是一种操作记录的体现。当然,这样的功能,完全可以自己在CRUD操作的时候去实现,但是秉持着程序的精简性和可靠性,用Spring 的@Audited自然是一种更好的方法了。

Spring审计功能简单易用(我的项目建立在Spring boot之上)。

假设我们的domain包下,有一个抽象的审计超类——AbstractAuditingEntity,其他的实体类都继承它。


@MappedSuperclass
@Audited
@EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditingEntity {

      @CreatedBy
      @Column(name = "created_by", nullable = false, length = 50, updatable = false)
      @JsonIgnore
      private String createdBy;

      @CreatedDate
      @Column(name = "created_date", nullable = false, updatable = false)
      @JsonIgnore
      private LocalDateTime createdDate = LocalDateTime.now();

      @LastModifiedBy
      @Column(name = "last_modified_by", length = 50)
      @JsonIgnore
      private String lastModifiedBy;

      @LastModifiedDate
      @Column(name = "last_modified_date")
      @JsonIgnore
      private LocalDateTime lastModifiedDate = LocalDateTime.now();

      // 省略对应的 set/get 方法......
}

简单讲一下类上三个注解的作用。

@MappedSuperclass API文档是这么写的: 指定一个类,其映射信息应用于从其继承的实体。 映射的超类没有为它定义的单独的表。使用MappedSuperclass注释指定的类可以以与实体相同的方式进行映射,除了映射将仅应用于其子类,因为映射的超类本身没有表。(谷歌翻译)翻译的虽然不是非常顺口,但大致还是能看懂的。意思就是说,应用这个注解的类(比如上面例子的AbstractAuditingEntity)在数据库里是没有表与它对应的,但是它的属性(这里的四个属性),将会被继承的子类所继承,并映射到子类在数据库中对应的这四个字段。那么显而易见,这个注解可以把众多实体类的公共属性提取出来,这也是此处的作用。
@Audited API文档是这么写的: 当应用于类时,表示其所有属性都应该被审计。 当应用于一个字段时,表示该字段应该被审计。没什么好解释的,谷歌这个翻译,很6。
@EntityListeners(AuditingEntityListener.class) 指定要用于实体或映射超类的回调侦听器类。 此注释可以应用于实体类或映射超类。相当于给当前的超类注册一个监听器,注册给谁呢,就是Spring提供的AuditingEntityListener这个类,从名字上看就大概揣测一二这个监听器的作用,监听一个实体创建或更新时的审计用的。

显然这三个注解都是必不可少的,当然如果不把公共实体抽取出来,而是在某个具体的类上(如Article)使用这些注解和声明定义这四个属性,那么@MappedSuperclass就没有必要了。

至于@CreatedBy@CreatedDate@LastModifiedBy@LastModifiedDate,那就对号入座了。

@JsonIgnore : 忽略改字段的序列化和反序列化。这么做,客户端将不会获得该字段。

这么做还是不够的,如果我们没有在JPA操作中启用审计功能的话。启用的方法很简单,只需要在主类上加上启用的注解即可:

@SpringBootApplication
@EnableJpaAuditing //在JPA操作中启用审计功能
public class Application 
{
    public static void main( String[] args )
    {
        SpringApplication.run(Application.class, args);
    }
}

跑起来我们会发现。createBylastModifiedBy的值并不会被相应地自动填上。因此我们还少了一个步骤——实现AuditorAware接口,并实现getCurrentAuditor方法,不然程序不知道创建者和最后修改者怎么给值。

@Component
public class SpringSecurityAuditorAware implements AuditorAware {

  @Override
  public String getCurrentAuditor() {
    // TODO 返回当前session会话中的账户名即可
  }
}

getCurrentAuditor方法中也体现了记录createdBylastModifiedBy的策略(包括是保存操作者用户名,还是电话号码或其他信息),一般情况下,当然是返回session中的账户信息(通常是账户名),因为肯定是这个账户修改的对应数据。

如此一来,在对普通实体类的CRUD操作时,便不用操心某条记录是谁创建的、啥时候创建的,又是谁最后一次更新的,最后一次更新是啥时候这样的破事儿了。

你可能感兴趣的:(Spring @Audited 审计——‘createdBy’,‘createdDate’,‘lastModifiedBy’和‘lastModifiedDate’)