Mybatis 拦截器

1.创建拦截器类

@Component
@Intercepts({
        @Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}),
        @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
        @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
})
public class MySqlInterceptor implements Interceptor {

    private  final Logger logger = LoggerFactory.getLogger(MySqlInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement statement = (MappedStatement) args[0];
        //验证是否需要进行拦截
        if(! this.checkDeal(statement)){
            return invocation.proceed();
        }
        //处理sql
        String sql = statement.getBoundSql(args[1]).getSql();
        this.dealSQL(sql, invocation);
        return invocation.proceed();
    }

    //验证是否需要进行拦截
    private boolean checkDeal(MappedStatement statement) {
        try {
            String id = statement.getId();
            String className = id.substring(0, id.lastIndexOf("."));
            String methodName = id.substring(id.lastIndexOf(".") + 1);
            Class<?> clazz = Class.forName(className);
            //验证类注解
            if(clazz.isAnnotationPresent(MyAnnotation.class)){
                MyAnnotation anno = AnnotationUtils.getAnnotation(clazz, MyAnnotation.class);
                String[] methods = anno.value();
                if(methods != null){
                    for(String method : methods){
                        if(methodName.equals(method)){
                            return true;
                        }
                    }
                }
            }
            //验证方法的注解
            Method[] methods = clazz.getMethods();
            if(methods != null){
                for(Method method : methods){
                    if(methodName.equals(method.getName()) && method.isAnnotationPresent(MyAnnotation.class)){
                        return true;
                    }
                }
            }
        }catch (Exception e){
            logger.error("验证拦截失败", e);
        }
        return false;
    }

    //处理sql
    private void dealSQL(String sql, Invocation invocation) {
        Object[] args = invocation.getArgs();
        MappedStatement statement = (MappedStatement) args[0];
        Object parameterObject = args[1];
        BoundSql boundSql = statement.getBoundSql(parameterObject);
        MappedStatement newStatement = rebuildStatement(statement, new BoundSqlSource(boundSql));
        MetaObject metaObject =  MetaObject.forObject(newStatement, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(),new DefaultReflectorFactory());

        //处理sql
        sql = sql.toUpperCase();
        if(sql.contains("INSERT INTO")){
            return;
        }
        if(sql.contains("WHERE")){
            sql = sql.replace("WHERE", "WHERE 1=1 AND");
        }else if(sql.contains("GROUP BY")){
            sql = sql.replace("GROUP BY", "WHERE 1=1 GROUP BY");
        }else if(sql.contains("ORDER BY")){
            sql = sql.replace("ORDER BY", "WHERE 1=1 ORDER BY");
        }else if(sql.contains("LIMIT")){
            sql = sql.replace("LIMIT", "WHERE 1=1 LIMIT");
        }else{
            sql = sql + " WHERE 1=1";
        }

        metaObject.setValue("sqlSource.boundSql.sql", sql);
        args[0] = newStatement;
        if(args.length >= 5){
            args[5] = newStatement.getBoundSql(parameterObject);
        }
    }

    //重建MappedStatement
    private MappedStatement rebuildStatement(MappedStatement statement, SqlSource sqlSource) {
        MappedStatement.Builder builder = new MappedStatement.Builder(statement.getConfiguration(), statement.getId(), sqlSource, statement.getSqlCommandType());
        builder.resource(statement.getResource());
        builder.fetchSize(statement.getFetchSize());
        builder.statementType(statement.getStatementType());
        builder.keyGenerator(statement.getKeyGenerator());
        if (statement.getKeyProperties() != null && statement.getKeyProperties().length > 0) {
            StringBuilder keyProperties = new StringBuilder();
            for (String keyProperty : statement.getKeyProperties()) {
                keyProperties.append(keyProperty).append(",");
            }
            keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
            builder.keyProperty(keyProperties.toString());
        }
        builder.timeout(statement.getTimeout());
        builder.parameterMap(statement.getParameterMap());
        builder.resultMaps(statement.getResultMaps());
        builder.resultSetType(statement.getResultSetType());
        builder.cache(statement.getCache());
        builder.flushCacheRequired(statement.isFlushCacheRequired());
        builder.useCache(statement.isUseCache());
        return builder.build();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {}

}

 

2.创建SqlSource

public class BoundSqlSource implements SqlSource {

    private BoundSql boundSql;

    public BoundSqlSource(BoundSql boundSql){
        this.boundSql = boundSql;
    }

    @Override
    public BoundSql getBoundSql(Object o) {
        return this.boundSql;
    }
}

 

3.创建自定义注解

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    @AliasFor("value")
    String[] method() default {};
    @AliasFor("method")
    String[] value() default  {};

}

 

4.在mapper中添加自定义注解

@MyAnnotation({"insert", "updateById", "selectById", "selectPage", "deleteById"})
public interface UserMapper extends BaseMapper<User> {
}

 

 

5.注意若使用了PageHelper,需要重新设置PageHelper自带拦截器的顺序

  a.pom文件中去除自动注入的包

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
            <exclusions>
                <exclusion>
                    <groupId>com.github.pagehelper</groupId>
                    <artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 

  b.重新创建PageHelperConfiguration配置类

import com.github.pagehelper.PageInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
@EnableConfigurationProperties({PageHelperProperties.class})
public class PageHelperConfiguration {

    @Autowired
    private PageHelperProperties properties;

    @Bean
    @ConfigurationProperties(prefix = "pagehelper")
    public Properties pageHelperProperties() {
        return new Properties();
    }

    @Bean
    public PageInterceptor addPageInterceptor() {
        PageInterceptor interceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.putAll(this.pageHelperProperties());
        properties.putAll(this.properties.getProperties());
        interceptor.setProperties(properties);
        return interceptor;
    }
}

 

  c.重新创建PageHelperProperties配置文件映射类

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Properties;

@ConfigurationProperties(prefix = "pagehelper")
public class PageHelperProperties {
    
    public static final String PAGEHELPER_PREFIX = "pagehelper";
    private Properties properties = new Properties();

    public PageHelperProperties() {
    }

    public Properties getProperties() {
        return this.properties;
    }

    public String getOffsetAsPageNum() {
        return this.properties.getProperty("offsetAsPageNum");
    }

    public void setOffsetAsPageNum(String offsetAsPageNum) {
        this.properties.setProperty("offsetAsPageNum", offsetAsPageNum);
    }

    public String getRowBoundsWithCount() {
        return this.properties.getProperty("rowBoundsWithCount");
    }

    public void setRowBoundsWithCount(String rowBoundsWithCount) {
        this.properties.setProperty("rowBoundsWithCount", rowBoundsWithCount);
    }

    public String getPageSizeZero() {
        return this.properties.getProperty("pageSizeZero");
    }

    public void setPageSizeZero(String pageSizeZero) {
        this.properties.setProperty("pageSizeZero", pageSizeZero);
    }

    public String getReasonable() {
        return this.properties.getProperty("reasonable");
    }

    public void setReasonable(String reasonable) {
        this.properties.setProperty("reasonable", reasonable);
    }

    public String getSupportMethodsArguments() {
        return this.properties.getProperty("supportMethodsArguments");
    }

    public void setSupportMethodsArguments(String supportMethodsArguments) {
        this.properties.setProperty("supportMethodsArguments", supportMethodsArguments);
    }

    public String getDialect() {
        return this.properties.getProperty("dialect");
    }

    public void setDialect(String dialect) {
        this.properties.setProperty("dialect", dialect);
    }

    public String getHelperDialect() {
        return this.properties.getProperty("helperDialect");
    }

    public void setHelperDialect(String helperDialect) {
        this.properties.setProperty("helperDialect", helperDialect);
    }

    public String getAutoRuntimeDialect() {
        return this.properties.getProperty("autoRuntimeDialect");
    }

    public void setAutoRuntimeDialect(String autoRuntimeDialect) {
        this.properties.setProperty("autoRuntimeDialect", autoRuntimeDialect);
    }

    public String getAutoDialect() {
        return this.properties.getProperty("autoDialect");
    }

    public void setAutoDialect(String autoDialect) {
        this.properties.setProperty("autoDialect", autoDialect);
    }

    public String getCloseConn() {
        return this.properties.getProperty("closeConn");
    }

    public void setCloseConn(String closeConn) {
        this.properties.setProperty("closeConn", closeConn);
    }

    public String getParams() {
        return this.properties.getProperty("params");
    }

    public void setParams(String params) {
        this.properties.setProperty("params", params);
    }

    public String getDefaultCount() {
        return this.properties.getProperty("defaultCount");
    }

    public void setDefaultCount(String defaultCount) {
        this.properties.setProperty("defaultCount", defaultCount);
    }

    public String getDialectAlias() {
        return this.properties.getProperty("dialectAlias");
    }

    public void setDialectAlias(String dialectAlias) {
        this.properties.setProperty("dialectAlias", dialectAlias);
    }
}

 

  d.设置pagehelper拦截器顺序在最前面

    @Autowired
    private PageInterceptor pageInterceptor;
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageInterceptor, ......});

 

posted @ 2021-02-17 17:52  晨M风  阅读(1518)  评论(0编辑  收藏  举报