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