SpringBoot+Mybatis配置自动填充字段拦截器


在项目开发中,基本都会有creator(创建者)create_time(创建时间)updater(更新者)update_time(更新时间)等这些固定字段需要设置,而这些字段的值又有一定的共性,每次手动设置就显得不够优雅。一个较好的解决方案是通过配置Mybatis的拦截器+注解的方式,实现通用字段(可根据项目需求修改下文中的字段)的自动填充。

创建相关注解

createBy.java

1
2
3
4
5
6
7
8
9
10
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateBy {
String value() default "";
}

CreateTime.java

1
2
3
4
5
6
7
8
9
10
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateBy {
String value() default "";
}

UpdateBy.java

1
2
3
4
5
6
7
8
9
10
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateBy {
String value() default "";
}

UpdateTime.java

1
2
3
4
5
6
7
8
9
10
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface CreateBy {
String value() default "";
}

配置拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class MybatisAutoFilledInterceptor implements Interceptor {

@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
// 获取 SQL 命令
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
// 只判断新增和修改
if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
// 获取参数
Object parameter = invocation.getArgs()[1];
// 批量操作时
if (parameter instanceof MapperMethod.ParamMap) {
MapperMethod.ParamMap map = (MapperMethod.ParamMap) parameter;
Object obj = map.get("list");
List<?> list = (List<?>) obj;
if (list != null) {
for (Object o : list) {
setParameter(o, sqlCommandType);
}
}
} else {
setParameter(parameter, sqlCommandType);
}
}
return invocation.proceed();
}

public void setParameter(Object parameter, SqlCommandType sqlCommandType) throws Throwable {
Class<?> clazz = parameter.getClass();
Field[] declaredFields;
// 如果常用字段提取了公共类 BaseEntity
// 判断BaseEntity是否是父类
if (BaseEntity.class.isAssignableFrom(clazz)) {
// 获取父类私有成员变量
declaredFields = clazz.getSuperclass().getDeclaredFields();
} else {
// 获取私有成员变量
declaredFields = clazz.getDeclaredFields();
}
for (Field field : declaredFields) {
if (SqlCommandType.INSERT.equals(sqlCommandType)) { // insert 语句插入 createBy
if (field.getAnnotation(CreateBy.class) != null) {
field.setAccessible(true);
field.set(parameter, SecurityUtils.getUsername());
}
if (field.getAnnotation(CreateTime.class) != null) { // insert 语句插入 createTime
field.setAccessible(true);
field.set(parameter, DateUtils.getNowDate());
}
}
if (SqlCommandType.UPDATE.equals(sqlCommandType)) {
if (field.getAnnotation(UpdateTime.class) != null) { // update 语句插入 updateTime
field.setAccessible(true);
field.set(parameter, DateUtils.getNowDate());
}
if (field.getAnnotation(UpdateBy.class) != null) { // update 语句插入 updateBy
field.setAccessible(true);
field.set(parameter, SecurityUtils.getUsername());
}
}
}
}
}

在需要自动填充的字段上添加注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;

/**
* 创建者
*/
@CreateBy
private String createBy;

/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@CreateTime
private Date createTime;

/**
* 更新者
*/
@UpdateBy
private String updateBy;

/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@UpdateTime
private Date updateTime;
}