SpringBoot整合SpringBatch項目,已將代碼開源至github,訪問地址:https://github.com/cmlbeliever/SpringBatch 歡迎star or fork!css
在框架整合的過程當中,因爲須要添加db讀寫分離配置,所以項目中有兩個DataSource,運行batch後報錯以下:java
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at com.cml.learning.framework.module.BaseModule.run(BaseModule.java:39)
at com.cml.learning.module.bat00X.Bat00XModule.main(Bat00XModule.java:20)
Caused by: java.lang.IllegalStateException: To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2
at org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.getConfigurer(AbstractBatchConfiguration.java:108)
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration.initialize(SimpleBatchConfiguration.java:114)
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$ReferenceTargetSource.createObject(SimpleBatchConfiguration.java:142)
at org.springframework.aop.target.AbstractLazyCreationTargetSource.getTarget(AbstractLazyCreationTargetSource.java:86)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192)
at com.sun.proxy.$Proxy55.getJobInstances(Unknown Source)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.getNextJobParameters(JobLauncherCommandLineRunner.java:131)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:212)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776)
... 5 common frames omitted
意思是要使用default BatchConfigurer,則項目中只能有一個Datasource。git
根據異常堆棧信息,找到拋出此異常的源碼位置和實現代碼:
org.springframework.batch.core.configuration.annotation.AbstractBatchConfigurationgithub
@Autowired(required = false)
private Collection<DataSource> dataSources;
protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) throws Exception {
if (this.configurer != null) {
return this.configurer;
}
if (configurers == null || configurers.isEmpty()) {
if (dataSources == null || dataSources.isEmpty()) {
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer();
configurer.initialize();
this.configurer = configurer;
return configurer;
} else if(dataSources != null && dataSources.size() == 1) {
DataSource dataSource = dataSources.iterator().next();
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
configurer.initialize();
this.configurer = configurer;
return configurer;
} else {
throw new IllegalStateException("To use the default BatchConfigurer the context must contain no more than" +
"one DataSource, found " + dataSources.size());
}
}
if (configurers.size() > 1) {
throw new IllegalStateException(
"To use a custom BatchConfigurer the context must contain precisely one, found "
+ configurers.size());
}
this.configurer = configurers.iterator().next();
return this.configurer;
}
根據源碼得知,當數據源不存的時候,BatchConfigure會將batch數據存儲到內存中,當數據源只有一個時,會根據數據源創建batch執行所須要的表。當數據源有多個的時候就拋出異常,這樣難怪,由於BatchConfigure在多個數據源的時候,它根本不知道要根據哪一個數據源創建batch執行所須要的表。
既然知道了緣由,只須要自定義BatchConfigure,而且在多數據源的狀況下指定一個默認的數據源便可解決。spring
實現步驟:
一、將框架SimpleBatchConfiguration,AbstractBatchConfiguration源碼複製出來
二、重寫AbstractBatchConfiguration.getConfigurer方法,設置默認數據源markdown
protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) throws Exception {
if (this.configurer != null) {
return this.configurer;
}
if (configurers == null || configurers.isEmpty()) {
if (defaultDataSource == null) {
throw new IllegalStateException("Data source can not be null!!!");
}
DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(defaultDataSource);
configurer.initialize();
this.configurer = configurer;
return configurer;
}
if (configurers.size() > 1) {
throw new IllegalStateException("To use a custom BatchConfigurer the context must contain precisely one, found " + configurers.size());
}
this.configurer = configurers.iterator().next();
return this.configurer;
}
三、添加註解,將重寫的BatchConfigure引入框架
@Import({ SimpleBatchConfiguration.class })
四、通過以上三個步驟,便可實現多數據源下SpringBatch啓動報錯問題ui
以上代碼已經整合到SpringBatch,已將代碼開源至github,訪問地址:https://github.com/cmlbeliever/SpringBatch 歡迎star or fork!this
若是有其餘更好的方法,還請不吝賜教。spa