Mybatis自定义拦截器,处理通用接口
2019-07-11 本文已影响17人
东方不喵
在日常开发业务场景中,经常要遇到对 实体进行通用性操作,如:
- 进行持久化时,出现的保存 创建人信息
- 更新数据时候,通用更新 操作人信息
- 指定接口自定义主键,等
为了解决这类问题,可以采用AOP 也可以采用拦截器,以下是采用MyBatis拦截器进行实现的
设置通用实体参数
@Data
public class BaseEntity {
@TableId
private String id;
private Date createTime;
/**
* 删除状态:
* 1 : 已删除
* 0 :未删除
*/
@Column(nullable = false)
private Integer isDeleted;
}
@Data
@MappedSuperclass
public class CommonBaseEntity extends BaseEntity implements CreatorSetterImpl, UpdaterSetterImpl {
/**
* 创建人ID
*/
private String creatorId;
/**
* 创建人姓名
*/
private String creatorName;
/**
* 最后更新人ID
*/
private String updaterId;
/**
* 最后更新人姓名
*/
private String updaterName;
/**
* 最后更新时间
*/
private Date updateTime;
}
创建用户接口 CreatorSetterImpl
public interface CreatorSetterImpl {
void setCreatorId(String creatorId);
void setCreatorName(String creatorName);
}
更新用户接口 UpdaterSetterImpl
public interface UpdaterSetterImpl {
void setUpdaterId(String updaterId);
void setUpdaterName(String updaterName);
void setUpdateTime(Date updateTime);
}
编写拦截器
/**
* @ClassName: BaseEntityMapperInterceptor
* @Author: ren
* @Description:
* @CreateTIme: 2019/7/8 0008 下午 5:26
**/
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class BaseEntityMapperInterceptor implements Interceptor, WapperInterface {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//获取代理对象,由于注解的反射,返回的为 确定类型 StatementHandler 的实例对象
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
//通过包装类,把statementHandler包装成一个可以调用反射的代理对象
MetaObject metaObject = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY);
//事实上拦截到的时RoutingStatementHandler,需要调用其中的 delegate 属性,才可以调用到 mappedStatement,然后通过反射调用获取到mappedStatement对象
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
DefaultParameterHandler parameterHandler = (DefaultParameterHandler) metaObject.getValue("delegate.parameterHandler");
//获取查询映射的名称
String id = mappedStatement.getId();
String methodName = id.substring(id.lastIndexOf(".") + 1);
Log4jUtils.getInstance(getClass()).debug("进行通用拦截:" + methodName);
Object parameter = parameterHandler.getParameterObject();
if (methodName.matches("save.*")) {
// 配置通用变量
initSaveMethod(parameter);
if (parameter instanceof HashMap) {
HashMap map = (HashMap) parameter;
map.forEach((k, v) -> {
if (v instanceof Collection) {
Collection collection = (Collection) v;
collection.forEach(obj -> {
// 配置通用变量
initSaveMethod(obj);
});
}
});
}
} else if (methodName.matches("update.*")) {
initUpdateMethod(parameter);
if (parameter instanceof HashMap) {
HashMap map = (HashMap) parameter;
map.forEach((k, v) -> {
if (v instanceof Collection) {
Collection collection = (Collection) v;
collection.forEach(obj -> {
// 配置通用变量
initUpdateMethod(obj);
});
}
});
}
}
return invocation.proceed();
}
/**
* 配置通用更新方法
*
* @param parameter
*/
private void initUpdateMethod(Object parameter) {
if (parameter instanceof UpdaterSetterImpl) {
UserEntity user = UserContext.getUserEntity();
if (null != user) {
UpdaterSetterImpl setter = (UpdaterSetterImpl) parameter;
setter.setUpdaterId(user.getUserId());
setter.setUpdaterName(user.getUsername());
setter.setUpdateTime(new Date());
}
}
}
/**
* 配置通用新增方法
*
* @param parameter
*/
private void initSaveMethod(Object parameter) {
if (parameter instanceof BaseEntity) {
Log4jUtils.getInstance(getClass()).debug("配置通用持久化变量");
BaseEntity baseEntity = (BaseEntity) parameter;
baseEntity.setId(IdWorker.getIdStr());
baseEntity.setIsDeleted(0);
baseEntity.setCreateTime(new Date());
}
if (parameter instanceof CreatorSetterImpl) {
Log4jUtils.getInstance(getClass()).debug("配置创建人信息");
UserEntity user = UserContext.getUserEntity();
if (null != user) {
CreatorSetterImpl setter = (CreatorSetterImpl) parameter;
setter.setCreatorId(user.getUserId());
setter.setCreatorName(user.getUsername());
}
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
在Myabtis配置中加入拦截器
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置全局变量 -->
<settings>
<!-- jdbc用getGeneratedKeys 获取数据库自增键值 -->
<setting name="useGeneratedKeys" value="true" />
<!-- 使用列别名替代列名 select name as title from table -->
<setting name="useColumnLabel" value="true" />
<!-- 开启驼峰命名法: Table(create_time) ->createTime -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<plugins>
<plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityMapperInterceptor"/>
<!--<plugin interceptor="com.example.oldguy.modules.commons.interceptors.BaseEntityInterceptor"/>-->
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"/>
</plugins>
</configuration>