概述
顾名思义,就是一个拦截器,和springmvc的拦截器,servlet的过滤器差不多,就是在执行前拦了一道,里面可以做一些自己的事情。
平时用的mybatisPlus较多,直接以com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
 为例。其内部维护了一个拦截器List,在拦截的时候for循环依次去调用这些拦截器,这时候的执行顺序就是list中的元素下标

mybatis官方介绍中可以拦截的类型共4种:
- Executor(拦截执行器的方法),- method=update包括了增删改,可以从- MappedStatement中获取实际执行的是哪种类型
- ParameterHandler(拦截参数的处理)
- ResultSetHandler(拦截结果集的处理)
- StatementHandler(拦截Sql语法构建的处理)
平时业务中拦截较多的就是增删改查,经典的就是分页拦截器–查询拦截器。
mybatisPlus拦截器Demo
参考了mybatisPlus的com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor
写完拦截器后记得要放到mybatisPlus的拦截器集合中去。
package com.xxx.xxx.xxx;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList;
import com.baomidou.mybatisplus.core.conditions.update.Update;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.mapper.Mapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyInnerInterceptor implements InnerInterceptor {
    /**
     *
     * @param executor  Executor(可能是代理对象)
     * @param ms        MappedStatement
     * @param parameter parameter
     * @throws SQLException
     */
    @Override
    public void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {
        SqlCommandType sqlCommandType = ms.getSqlCommandType();
        String msId = ms.getId();
        if(!Objects.equals(SqlCommandType.UPDATE, sqlCommandType)){
            return;
        }
        //更新
        if (parameter instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) parameter;
            //被更新的实体类的对象在mybatis这里都是用et做别名
            Object et = map.getOrDefault("et", null);
            //对应mapper的class
            final String className = getMapperClassName(msId);
            //mapper使用的更新方法
            final String methodName = getMapperMethodName(msId);
            //实体类的class
            Class<?> entityClass = getEntityClass(className);
            //获取实体类的字段信息
            TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
            //当前实体类的属性集合
            List<TableFieldInfo> fieldList = tableInfo.getFieldList();
            // updateById(et), update(et, wrapper);
            if(Objects.nonNull(et)){
                try {
                    for (TableFieldInfo fieldInfo : fieldList) {
                        //field
                        Field field = fieldInfo.getField();
                        //获取column
                        String column = fieldInfo.getColumn();
                        //旧的value
                        Object oldValue = field.get(et);
                    }
                } catch (IllegalAccessException e) {
                    throw ExceptionUtils.mpe(e);
                }
                // update(LambdaUpdateWrapper) or update(UpdateWrapper)
            }else if (map.entrySet().stream().anyMatch(t -> Objects.equals(t.getKey(), "ew"))) {
                Object ew = map.get("ew");
                if (!(ew instanceof AbstractWrapper && ew instanceof Update)) {
                    return;
                }
                final Map<String, Object> paramNameValuePairs = ((AbstractWrapper<?, ?, ?>) ew).getParamNameValuePairs();
                for (TableFieldInfo fieldInfo : fieldList) {
                    //field
                    Field field = fieldInfo.getField();
                    //获取column
                    String column = fieldInfo.getColumn();
                    Wrapper<?> wrapper = (Wrapper<?>) ew;
                    //查询更新条件中指定的列名对应的值
                    String valueKey = getValueKey(column, wrapper);
                    final Object conditionValue = paramNameValuePairs.get(valueKey);
                }
            }
        }
    }
    /**
     * 查询更新条件中指定的列名对应的值
     * 即查询 where xxx = value 这个条件中的 xxx 对应的 value
     * @param column
     * @param wrapper
     * @return
     */
    private String getValueKey(String column, Wrapper<?> wrapper){
        Pattern pattern = Pattern.compile("#\\{ew\\.paramNameValuePairs\\.(" + "MPGENVAL" + "\\d+)\\}");
        final NormalSegmentList segments = wrapper.getExpression().getNormal();
        String fieldName = null;
        ISqlSegment eq = null;
        String valueKey = null;
        for (ISqlSegment segment : segments) {
            String sqlSegment = segment.getSqlSegment();
                //如果字段已找到并且当前segment为EQ
            if(Objects.nonNull(fieldName) && segment == SqlKeyword.EQ){
                eq = segment;
                //如果EQ找到并且value已找到
            }else if(Objects.nonNull(fieldName) && Objects.nonNull(eq)){
                Matcher matcher = pattern.matcher(sqlSegment);
                if(matcher.matches()){
                    valueKey = matcher.group(1);
                    return valueKey;
                }
                //处理嵌套
            }else if (segment instanceof Wrapper){
                if(null != (valueKey = getValueKey(column, ((Wrapper<?>) segment)))){
                    return valueKey;
                }
                //判断字段是否是要查找字段
            }else if(Objects.equals(column, sqlSegment)){
                fieldName = sqlSegment;
            }
        }
        return valueKey;
    }
    private String getMapperMethodName(String msId){
        return msId.substring(msId.lastIndexOf('.') + 1);
    }
    private String getMapperClassName(String msId){
        return msId.substring(0, msId.lastIndexOf('.'));
    }
    /**
     * 通过mapper上实体类信息获取实体类class
     * @param className
     * @return
     */
    private Class<?> getEntityClass(String className){
        try {
            return ReflectionKit.getSuperClassGenericType(Class.forName(className), Mapper.class, 0);
        } catch (ClassNotFoundException e) {
            throw ExceptionUtils.mpe(e);
        }
    }
}
注册拦截器
@Bean
public MyInnerInterceptor myInnerInterceptor(ApplicationContext applicationContext){
    MyInnerInterceptor myInnerInterceptor = new MyInnerInterceptor();
    MybatisPlusInterceptor bean = applicationContext.getBean(MybatisPlusInterceptor.class);
    bean.addInnerInterceptor(myInnerInterceptor);
    return myInnerInterceptor;
}



















