配置类
import java.util.Properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mybatis配置
*/
@Configuration
public class MybatisConfiguration {
/**
* 注册拦截器
*/
@Bean
public MybatisInterceptor mybatisInterceptor() {
MybatisInterceptor interceptor = new MybatisInterceptor();
Properties properties = new Properties();
// 可以调用properties.setProperty方法来给拦截器设置一些自定义参数
interceptor.setProperties(properties);
return interceptor;
}
}
拦截器
? ? ? ? 方法枚举
public enum SqlCommandType {
UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH;
}
import java.util.Map;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.executor.Executor;
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.Plugin;
import org.apache.ibatis.plugin.Signature;
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class,
Object.class})})
@Slf4j
public class MybatisInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//真正拦截的方法
String userName = ClientContext.getUserName();
// 获取第一个参数
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
Object paramObj = invocation.getArgs()[1];
if (ms.getId().contains("updateStatusByIds")) {
if (ms.getSqlCommandType() == SqlCommandType.UPDATE) {
if (paramObj instanceof Map) {
Object value = ((ParamMap) paramObj).get("updater");
// if (Objects.isNull(value)) {
((ParamMap) paramObj).put("updater", "myTest");
// }
}
}
}
//更新状态拦截,添加用户名,更新时间信息
Object[] args = invocation.getArgs();
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
//返回代理类
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
invocation的第一个参数
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
?第二个参数强转:Object value = ((ParamMap) paramObj).get("updater");
简单试验之后:以下四个可以作为Signature中type的参数,没猜错的话,后面的method就是括号后的值
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
signature参数解释:
? type : 这儿主要是拦截对象的类型,是前面拦截器介绍中的四种之一,或多种(源码中type返回值是数组) method : 方法只能是一个值, ? args: 值是前面介绍的四种拦截器括号中的内容,可以有多个.
@Intercepts(
{@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class}),
})
public class MybatisInterceptor implements Interceptor {
private static final Logger logger = LoggerFactory.getLogger(MybatisInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement mappedStatements = (MappedStatement) args[0];
Map<String, Object> paramMap = new MapperMethod.ParamMap<>();
if (args[1] != null) {
if (args[1] instanceof MapperMethod.ParamMap) {
paramMap.putAll((Map) args[1]);
} else if (BeanUtils.isSimpleValueType(args[1].getClass())) {
String mapperId = mappedStatements.getId();
Class<?> paramType = args[1].getClass();
String clazzName = mapperId.substring(0, mapperId.lastIndexOf("."));
String methodName = mapperId.substring(mapperId.lastIndexOf(".") + 1);
Class<?> target = Class.forName(clazzName);
Method method = target.getMethod(methodName, paramType);
Parameter[] params = method.getParameters();
String paramName = params[0].getName();
paramMap.put(paramName, args[1]);
} else {
List<Field> fields = new ArrayList<>();
getAllFields(fields, args[1].getClass());
for (Field field : fields) {
Object fieldValue = null;
String fieldName = field.getName();
try {
fieldValue = (new PropertyDescriptor(fieldName, args[1].getClass())).getReadMethod().invoke(args[1]);
} catch (Exception var9) {
logger.error(var9.getMessage(), var9);
}
paramMap.putIfAbsent(field.getName(), fieldValue);
}
}
}
paramMap.put("key", "value");
args[1] = paramMap;
return invocation.proceed();
}
private List<Field> getAllFields(List<Field> fields, Class<?> type) {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
if (type.getSuperclass() != null) {
this.getAllFields(fields, type.getSuperclass());
}
return fields;
}
}
|