您好,登錄后才能下訂單哦!
這篇文章主要介紹了SpringBoot整合Mybatis自定義攔截器不起作用怎么辦,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Mybatis插件生效的方式:
該方式和Spring無關,是通過反射的形式創建插件對象,此時會執行org.apache.ibatis.plugin.Interceptor#setProperties方法,以讀取配置參數。
mybatis: mapper-locations: classpath*:/mapping/*.xml type-aliases-package: com.tellme.pojo #讀取全局配置的地址 config-location: classpath:mybatis-config.xml
在resource目錄下配置mybatis的全局配置:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="useGeneratedKeys" value="true"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25000"/> </settings> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer"/> <typeAlias alias="Long" type="java.lang.Long"/> <typeAlias alias="HashMap" type="java.util.HashMap"/> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/> <typeAlias alias="ArrayList" type="java.util.ArrayList"/> <typeAlias alias="LinkedList" type="java.util.LinkedList"/> </typeAliases> <!--配置的插件名--> <plugins> <plugin interceptor="com.xxx.yyy.plugins.PrintSqlInfoInterceptor"/> </plugins> </configuration>
網上很多方案說:mybatis自定義攔截器上加上@Component注解便可以生效。但是我將自定義攔截器放入到Spring容器中,自定義攔截器卻失效了。
然后找到了springboot配置多數據源后mybatis攔截器失效文章,說是自定義配置了數據源導致了攔截器失效。
源碼位置:org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
@Configuration @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }) @ConditionalOnBean(DataSource.class) @EnableConfigurationProperties(MybatisProperties.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class MybatisAutoConfiguration { private static Log log = LogFactory.getLog(MybatisAutoConfiguration.class); @Autowired private MybatisProperties properties; //會依賴注入Spring容器中所有的mybatis的Interceptor攔截器 @Autowired(required = false) private Interceptor[] interceptors; ... @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } factory.setConfiguration(properties.getConfiguration()); //手動放入到了setPlugins方法中。 if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } return factory.getObject(); } ... }
上面源碼中:自動注入了Interceptor[]數組(我們只需將mybatis的自定義攔截器對象放入到Spring容器中)。后續放入了sqlSessionFactory中。
但是項目中雖然自定義配置了sqlSessionFactory類,但卻未設置factory.setPlugins(this.interceptors);。導致即使將自定義攔截器放入到Spring容器,但卻不生效。
解決方法,需要手動修改自定義的sqlSessionFactory類。
這種情況下,mybatis自定義攔截器會被執行兩次。即在mybatis-config.xml配置的攔截器會通過反射的方式創建攔截器,放入Spring容器的攔截器也會被初始化。
源碼位置:org.mybatis.spring.SqlSessionFactoryBean#buildSqlSessionFactory
protected SqlSessionFactory buildSqlSessionFactory() throws IOException { Configuration configuration; ...讀取屬性中的plugins,即org.mybatis.spring.SqlSessionFactoryBean#setPlugins設置的。 if (!isEmpty(this.plugins)) { for (Interceptor plugin: this.plugins) { configuration.addInterceptor(plugin); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Registered plugin: '" + plugin + "'"); } } } ...解析xml配置(通過反射創建攔截器對象) if (xmlConfigBuilder != null) { try { xmlConfigBuilder.parse(); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'"); } } catch(Exception ex) { throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex); } finally { ErrorContext.instance().reset(); } } return this.sqlSessionFactoryBuilder.build(configuration); }
最終會執行到:
private void pluginElement(XNode parent) throws Exception { if (parent != null) { for (XNode child: parent.getChildren()) { String interceptor = child.getStringAttribute("interceptor"); Properties properties = child.getChildrenAsProperties(); //反射創建mybatis的插件。 Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance(); interceptorInstance.setProperties(properties); configuration.addInterceptor(interceptorInstance); } } }
開發過程中經常回需要對要執行的sql加以自定義處理,比如分頁,計數等。通過 MyBatis 提供的強大機制,使用插件是非常簡單的,只需實現 Interceptor 接口,并指定想要攔截的方法簽名即可。
@Intercepts({@Signature(type = Executor.class,method = "query",args = {MappedStatement.class,Object.class, RowBounds.class,ResultHandler.class})}) public class MyPageInterceptor implements Interceptor { private static final Logger logger= LoggerFactory.getLogger(MyPageInterceptor.class); @Override public Object intercept(Invocation invocation) throws Throwable { logger.warn(invocation.toString()); return invocation.proceed(); } @Override public Object plugin(Object o) { return Plugin.wrap(o,this); } @Override public void setProperties(Properties properties) { logger.warn(properties.toString()); } }
我的配置
mybatis: type-aliases-package: me.zingon.pagehelper.model mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true default-fetch-size: 100 default-statement-timeout: 30
在springboot中要給mybatis加上這個攔截器,有三種方法,前兩種方法在啟動項目時不會自動調用自定義攔截器的setProperties方法。
直接給自定義攔截器添加一個@Component注解,當調用sql時結果如下,可以看到攔截器生效了,但是啟動時候并沒有自動調用setProperties方法。
在配置類里添加攔截器,這種方法結果同上,也不會自動調用setProperties方法。
@Configuration public class MybatisConfig { @Bean ConfigurationCustomizer mybatisConfigurationCustomizer() { return new ConfigurationCustomizer() { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { configuration.addInterceptor(new MyPageInterceptor()); } }; } }
這種方法就是跟以前的配置方法類似,在yml配置文件中指定mybatis的xml配置文件,注意config-location屬性和configuration屬性不能同時指定
mybatis: config-location: classpath:mybatis.xml type-aliases-package: me.zingon.pagehelper.model mapper-locations: classpath:mapper/*.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="me.zingon.pacargle.model"/> </typeAliases> <plugins> <plugin interceptor="me.zingon.pagehelper.interceptor.MyPageInterceptor"> <property name="dialect" value="oracle"/> </plugin> </plugins> </configuration>
可以看到,在啟動項目的時候setProperties被自動調用了
前兩種方法可以在初始化自定義攔截器的時候通過 @Value 注解直接初始化需要的參數。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“SpringBoot整合Mybatis自定義攔截器不起作用怎么辦”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。