ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Mybatis 拦截器

2021-02-17 18:04:21  阅读:104  来源: 互联网

标签:拦截器 return String properties statement sql Mybatis public


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, ......});

 

标签:拦截器,return,String,properties,statement,sql,Mybatis,public
来源: https://www.cnblogs.com/vettel0329/p/14409215.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有