携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
用户自定义的拦截器也被称为 MyBatis 插件。
有些公司对数据表的表结构有一些规范,要求数据表必须包含某些字段,如创建人姓名(create_by)、创建时间(create_time)、编辑人姓名(update_by)、最后编辑时间(update_time)等。
怎样设置这些公共字段的属性值呢?
最无脑的做法是在每次新增或者编辑数据时手动设置这些字段的属性值。这样做确实可以实现功能,但是重复代码太多,不够优雅。
有没有比较简便、稍微优雅点的方式呢?
当然是有的。
因为我们数据库持久层框架使用的是 MyBatis,我们可以使用 MyBatis 的 拦截器(Interceptor)来实现此功能。
拦截器代码实现
我们定义了一个实体类
BaseEntity,所有实体继承该实体。
BaseEntity.java —— Entity基类
@Data
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/** 创建者 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
BaseEntityInterceptor.java —— 自定义 Mybatis 拦截器
@Slf4j
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class BaseEntityInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameter = invocation.getArgs()[1];
if (parameter instanceof BaseEntity) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String currentUsername = null;
if (principal instanceof UserDetailsImpl) {
UserDetailsImpl userDetails = (UserDetailsImpl) principal;
currentUsername = userDetails.getUsername();
}
BaseEntity baseEntity = (BaseEntity) parameter;
if (Objects.equals(SqlCommandType.INSERT, mappedStatement.getSqlCommandType())) {
baseEntity.setCreateBy(currentUsername);
baseEntity.setCreateTime(new Date());
} else if (Objects.equals(SqlCommandType.UPDATE, mappedStatement.getSqlCommandType())) {
baseEntity.setUpdateBy(currentUsername);
baseEntity.setUpdateTime(new Date());
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// Interceptor.super.setProperties(properties);
}
}
拦截器配置
在 MyBatis 的配置文件里配置自定义拦截器:
<plugins>
<plugin interceptor="com.jasmine.plugin.BaseEntityInterceptor" />
</plugins>
这样,我们在新增或者修改数据的时候,公共字段就自动赋值了。
如果觉得文章写得还凑合,还麻烦你动动小手帮忙点个赞呗。你的支持是我更文的动力。目前在写的系列有下面几个系统:
- MyBatis源码解读
- 设计模式
- 一起学Three.js
- Spring Boot
- Spring Cloud
都是一些平时工作中用到的知识点的个人总结和学习笔记。