mybatis拦截器

配置类




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 允许使用插件来拦截的方法调用包括:

  1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  2. ParameterHandler (getParameterObject, setParameters)
  3. ResultSetHandler (handleResultSets, handleOutputParameters)
  4. 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;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值