PageHelper:在系統中發現了多個分頁外掛,請檢查系統配置
專案執行環境:Spring Boot + Mybatis/Mybatis-plus + PageHelper
專案前提:本專案引入了一個由其它Spring Boot專案打包成的JAR包(這個很關鍵)
問題描述
在IDEA中除錯程式,分頁正常;但通過WAR包部署時報錯:“在系統中發現了多個分頁外掛,請檢查系統配置”,具體報錯資訊如下:
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.lang.RuntimeException: 在系統中發現了多個分頁外掛,請檢查系統配置! ### Cause: java.lang.RuntimeException: 在系統中發現了多個分頁外掛,請檢查系統配置!
錯誤的解決方法
根據網上的方法嘗試設定@SpringBootApplication(exclude = PageHelperAutoConfiguration.class)
,之後獨立WAR包部署的專案可以正常執行,但是在IDEA中分頁功能卻失效了。
解決方法
上面的解決方法雖然沒能最終解決問題,但是提供了一個思路,提示可能是自動配置的過程中出了問題
在上面的解決方法中設定@SpringBootApplication(exclude = PageHelperAutoConfiguration.class)
之後獨立WAR包部署的專案可以正常執行,但是在IDEA中分頁功能卻失效了。說明確實是自動配置的問題,自動配置是需要的,但是如果配置兩次的話就會報出“多個分頁外掛”的錯誤!
問題分析
-
不管是在IDEA中除錯還是獨立WAR包部署,測試環境和生產環境基本一致,唯一不同是本地測試用的是Spring Boot的內建Tomcat啟動的,而生產環境是執行在獨立Tomcat中的。
而用內建Tomcat啟動類啟動沒有問題,但是WAR包部署到獨立Tomcat就會出現這個報錯,所以要看看有什麼區別。 -
在將Spring Boot專案打包成WAR包時需要配置Application啟動類繼承SpringBootServletInitializer,並重寫configure方法,而configure方法的作用就是要指定啟動資源。
-
根據前面的分析可以猜測,是PageHelper相關的資源被指定了兩次,所以啟動的時候載入了兩次這個資源,兩次都自動配置了PageHelper外掛,從而導致報錯。所以可以根據這個思路去尋找專案中有哪些地方繼承了SpringBootServletInitializer,並重寫了configure方法。
-
很簡單地,可以猜到可能是自己引入的那個由其它Spring Boot專案打包成的JAR包出的問題。
正常來說,將一個Spring Boot專案打包成JAR包時要刪除其Application啟動類,但是在某次打包時由於疏忽忘記了這個步驟,所以導致之後生成的WAR包中有兩個繼承了SpringBootServletInitializer的類,所以導致PageHelper外掛被配置了兩次。
- 修改將被打包成JAR包的Spring Boot專案,去掉多餘的Application,即可解決問題。
說明
本人追溯到的原因只是一種情況,但是可以按照這個思路去找問題。
拓展部分
PageHelper的自動配置類原始碼分析:PageHelperAutoConfiguration
@Configuration
@ConditionalOnBean(SqlSessionFactory.class)
@EnableConfigurationProperties(PageHelperProperties.class)
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class PageHelperAutoConfiguration {
@Autowired
private List<SqlSessionFactory> sqlSessionFactoryList;
@Autowired
private PageHelperProperties properties;
/**
* 接受分頁外掛額外的屬性
*
* @return
*/
@Bean
@ConfigurationProperties(prefix = PageHelperProperties.PAGEHELPER_PREFIX)
public Properties pageHelperProperties() {
return new Properties();
}
@PostConstruct
public void addPageInterceptor() {
PageInterceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
//先把一般方式配置的屬性放進去
properties.putAll(pageHelperProperties());
//在把特殊配置放進去,由於close-conn 利用上面方式時,屬性名就是 close-conn 而不是 closeConn,所以需要額外的一步
properties.putAll(this.properties.getProperties());
interceptor.setProperties(properties);
for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
sqlSessionFactory.getConfiguration().addInterceptor(interceptor);
}
}
}
- 從原始碼也可以看出兩次自動配置會加入了兩個攔截器PageInterceptor,所以才會提示“多個外掛”;
- 加上
exclude=PageHelperAutoConfiguration.class
之後,相當於排除了PageHelperAutoConfiguration.class,即不讓PageHelper自動配置,所以取消自動配置後又出現分頁失效的問題。