实现MyBatis拦截器自动填充创建、更新时间等字段属性值
1.创建DataFill注解
package com.risesun.common.core.annotation;
import org.apache.ibatis.mapping.SqlCommandType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author LiXiangrong
* @Description 这是用来默认填充的注释 value支持spel表达式
* @Date 2023/03/13 16:30:45
**/
@Documented
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DataFill
{
String value();
/**
* 填充的类型
* @return
*/
Class fillClass();
/**
* sql插入类型
* @return 返回数组
*/
SqlCommandType[] commandTypes();
}
2.格式化方法Func
package com.risesun.common.core.utils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @Author LiXiangrong
* @Description 公用函数类
* @Date 2023/03/13 14:13:20
**/
public class Func
{
/**
* 日志
*/
private static final Logger LOGGER = LoggerFactory.getLogger(Func.class);
/**
* @Author LiXiangrong
* @Description 构造函数私有化
* @Date 2023/03/13 17:09:38
**/
private Func()
{
}
/**
* @Author LiXiangrong
* @Description 安全的进行字符串 format
* @Date 2023/03/13 16:09:13
* @Param target
* @Param params
* @Return java.lang.String
**/
public static String formatStr(String target, Object... params)
{
if (target.contains("%s") && ArrayUtils.isNotEmpty(params))
{
return String.format(target, params);
}
return target;
}
}
3.SPEL表达式的定义
// 自动插入创建时间和更新时间按SPEL表达式
public static final String DATE_DEFAULT_SPEL = "T(com.risesun.common.core.utils.DateUtil).getCurrentDate()";
// 自动插入登录用户名按SPEL表达式
public static final String USERNAME_DEFAULT_SPEL = "T(com.risesun.common.security.utils.SecurityUtils).getUsername()";
// 自动填充UUID
public static final String UUID_DEFAULT_SPEL = "T(com.risesun.common.core.utils.uuid.IdUtils).randomUUID()";
// 自动填充雪花算法ID
public static final String ASSIGN_ID = "T(com.risesun.business.util.CommonUtils).assignId()";
// 自动填充登陆人id(Long类型)
public static final String USER_ID = "T(com.risesun.common.security.utils.SecurityUtils).getUserId()";
// 自动填充登陆人id(String类型)
public static final String USERID_DEFAULT_SPEL = "T(com.risesun.common.security.utils.SecurityUtils).getUserId().toString()";
4.创建自定义AutoFillInterceptor拦截器实现Mybatis的拦截器接口
package com.risesun.business.config;
import com.risesun.common.core.annotation.DataFill;
import com.risesun.common.core.utils.Func;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
/**
* @Author LiXiangrong
* @Description MyBatis拦截器填充属性值
* @Date 2023/03/13 17:00:33
**/
@Component
@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class AutoFillInterceptor implements Interceptor
{
public static final Logger log = LoggerFactory.getLogger(AutoFillInterceptor.class);
public static final ExpressionParser SPEL_EXPRESSION = new SpelExpressionParser();
@Override
public Object intercept(Invocation invocation) throws Throwable
{
Object[] params = invocation.getArgs();
MappedStatement mappedStatements = (MappedStatement) params[0];
SqlCommandType sqlCommandType = mappedStatements.getSqlCommandType();
log.info("开始自动填充...");
setDefaultValue(params[1], sqlCommandType);
return invocation.proceed();
}
/*
* @Author LiXiangrong
* @Description setDefaultValue
* @Date 2023/03/13 17:02:17
* @Param metaObject
* @Param sqlCommandType
* @Return void
**/
private void setDefaultValue(Object metaObject, SqlCommandType sqlCommandType)
{
Expression expression;
List<Field> needFillList = new ArrayList<>();
//找到所有有DataFill注解的属性
ReflectionUtils.doWithFields(metaObject.getClass(), needFillList::add, getFieldFilter(sqlCommandType));
//将所有的属性进行赋值
for (Field field : needFillList)
{
DataFill fill = field.getAnnotation(DataFill.class);
if (null != fill)
{
expression = SPEL_EXPRESSION.parseExpression(fill.value());
Object fillObj = expression.getValue();
if (fill.fillClass().isInstance(fillObj))
{
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, metaObject, fillObj);
//this.setFieldValByName(field.getName(), fillObj, metaObject);
} else
{
throw new RuntimeException(Func.formatStr("默认值填充错误,{}的类型应该为{},传入的类型与其不兼容", field.getName(), fill.fillClass().getName()));
}
}
}
}
/**
* @Author LiXiangrong
* @Description getFieldFilter
* @Date 2023/03/13 17:03:07
* @Param sqlCommandType
* @Return org.springframework.util.ReflectionUtils.FieldFilter
**/
private ReflectionUtils.FieldFilter getFieldFilter(SqlCommandType sqlCommandType)
{
return field ->
{
DataFill fill = field.getAnnotation(DataFill.class);
if (null == sqlCommandType)
{
return false;
}
return (fill != null && Arrays.asList(fill.commandTypes()).contains(sqlCommandType));
};
}
@Override
public Object plugin(Object target)
{
return Interceptor.super.plugin(target);
}
@Override
public void setProperties(Properties properties)
{
Interceptor.super.setProperties(properties);
}
}
评论 (0)