隨着項目的規模的不斷擴大,Spring Batch的配置文件,也是一個頭疼的問題,本人試了很多次,建議的配置方式如下:
基礎配置放在一個文件中applicationContext-batch.xml:
<beans:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<bean:bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<bean:property name="transactionManager" ref="transactionManager" />
</bean:bean>
<bean:bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager">
</bean:bean>
<bean:bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<bean:property name="jobRepository" ref="jobRepository" />
<bean:property name="taskExecutor">
<bean:bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"></bean:bean>
</bean:property>
</bean:bean>
</beans:beans>
一個業務場景對應一個配置文件applicationContext-batch-mysteps.xml:
<beans:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<flow id="mysteps_flow">
<step id="mysteps_flow_first" parent="mysteps_first" next="mysteps_flow_second"></step>
<step id="mysteps_flow_second" parent="mysteps_second" next="mysteps_flow_third"></step>
<step id="mysteps_flow_third" parent="mysteps_third"></step>
</flow>
<step id="mysteps_first">
<tasklet ref="first"></tasklet>
</step>
<step id="mysteps_second">
<tasklet ref="second"></tasklet>
</step>
<step id="mysteps_third">
<tasklet ref="third"></tasklet>
</step>
<bean:bean id="first" class="com.test.tasklet.MyFirstTasklet" scope="step">
</bean:bean>
<bean:bean id="second" class="com.test.tasklet.MySecondTasklet" scope="step">
</bean:bean>
<bean:bean id="third" class="com.test.tasklet.MyThirdTasklet" scope="step">
</bean:bean>
</beans:beans>
業務場景的配置,最好到Flow級別。
所有的Job放在同一個配置文件中applicationContext-batch-job.xml:
<beans:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<job id="fJob">
<step id="fJob_begin" parent="mysteps_first" next="fJob_second"></step>
<flow id="fJob_second" parent="mysteps_flow"></flow>
</job>
<job id="sJob">
<step id="sJob_begin" parent="mysteps_first"></step>
</job>
</beans:beans>
這樣,我們只需要看Job的配置文件就能看到所有的可以執行的Job。
一個Flow是一些Steps的集合,用好parent屬性,parent可以讓一個step或者flow繼承父元素的所有屬性。
main函數:
/**
*
*/
package com.test.springbatch;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* @author hadoop
*
*/
public class AppMain {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context;
JobParametersBuilder jobPara = new JobParametersBuilder(); //設置文件路徑參數
context = new FileSystemXmlApplicationContext(new String[]{"classpath:applicationContext-batch-mysteps.xml",
"classpath:applicationContext-batch.xml", "classpath:applicationContext-batch-job.xml"});
Job fJob = (Job)context.getBean("fJob");
Job sJob = (Job)context.getBean("sJob");
JobLauncher launcher = (JobLauncher)context.getBean("jobLauncher");
try {
launcher.run(fJob, jobPara.toJobParameters());
//launcher.run(sJob, jobPara.toJobParameters());
} catch (JobExecutionAlreadyRunningException e) {
e.printStackTrace();
} catch (JobRestartException e) {
e.printStackTrace();
} catch (JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
} catch (JobParametersInvalidException e) {
e.printStackTrace();
}
}
}
三個task類:
/**
*
*/
package com.test.tasklet;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
/**
* @author hadoop
*
*/
public class MyFirstTasklet implements Tasklet {
/* (non-Javadoc)
* @see org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)
*/
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1)
throws Exception {
for(int i = 0; i < 10; i++)
{
System.out.println(Thread.currentThread().getName() + "F" + i);
Thread.sleep(1000);
}
return RepeatStatus.FINISHED;
}
}
/**
*
*/
package com.test.tasklet;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
/**
* @author hadoop
*
*/
public class MySecondTasklet implements Tasklet {
/* (non-Javadoc)
* @see org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)
*/
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1)
throws Exception {
for(int i = 0; i < 10; i++)
{
System.out.println(Thread.currentThread().getName() + "S" + i);
Thread.sleep(1000);
}
return RepeatStatus.FINISHED;
}
}
/**
*
*/
package com.test.tasklet;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
/**
* @author hadoop
*
*/
public class MyThirdTasklet implements Tasklet {
/* (non-Javadoc)
* @see org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)
*/
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1)
throws Exception {
for(int i = 0; i < 10; i++)
{
System.out.println(Thread.currentThread().getName() + "T" + i);
Thread.sleep(1000);
}
return RepeatStatus.FINISHED;
}
}
執行結果:
INFO [org.springframework.context.support.FileSystemXmlApplicationContext] - Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@68fe748f: display name [org.springframework.context.support.FileSystemXmlApplicationContext@68fe748f]; startup date [Sat May 04 09:46:27 CST 2013]; root of context hierarchy
INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [applicationContext-batch-mysteps.xml]
INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [applicationContext-batch.xml]
INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from class path resource [applicationContext-batch-job.xml]
INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Overriding bean definition for bean 'fJob': replacing [Generic bean: class [org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.batch.core.configuration.xml.JobParserJobFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Overriding bean definition for bean 'sJob': replacing [Generic bean: class [org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.batch.core.configuration.xml.JobParserJobFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
INFO [org.springframework.context.support.FileSystemXmlApplicationContext] - Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@68fe748f]: org.springframework.beans.factory.support.DefaultListableBeanFactory@1232784a
INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Overriding bean definition for bean 'first': replacing [Generic bean: class [com.test.tasklet.MyFirstTasklet]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext-batch-mysteps.xml]] with [Root bean: class [org.springframework.batch.core.scope.util.PlaceholderProxyFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [applicationContext-batch-mysteps.xml]]
INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Overriding bean definition for bean 'second': replacing [Generic bean: class [com.test.tasklet.MySecondTasklet]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext-batch-mysteps.xml]] with [Root bean: class [org.springframework.batch.core.scope.util.PlaceholderProxyFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [applicationContext-batch-mysteps.xml]]
INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Overriding bean definition for bean 'third': replacing [Generic bean: class [com.test.tasklet.MyThirdTasklet]; scope=step; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=false; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext-batch-mysteps.xml]] with [Root bean: class [org.springframework.batch.core.scope.util.PlaceholderProxyFactoryBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in BeanDefinition defined in class path resource [applicationContext-batch-mysteps.xml]]
INFO [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1232784a: defining beans [org.springframework.batch.core.scope.internalStepScope,org.springframework.beans.factory.config.CustomEditorConfigurer,org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor,mysteps_flow_first,mysteps_flow_second,mysteps_flow_third,mysteps_flow,mysteps_first,mysteps_second,mysteps_third,first,second,third,jobRepository,transactionManager,jobLauncher,fJob_begin,fJob,sJob_begin,sJob,lazyBindingProxy.first,lazyBindingProxy.second,lazyBindingProxy.third]; root of factory hierarchy
INFO [org.springframework.batch.core.launch.support.SimpleJobLauncher] - Job: [FlowJob: [name=fJob]] launched with the following parameters: [{}]
INFO [org.springframework.batch.core.job.SimpleStepHandler] - Executing step: [fJob_begin]
SimpleAsyncTaskExecutor-1F0
SimpleAsyncTaskExecutor-1F1
SimpleAsyncTaskExecutor-1F2
SimpleAsyncTaskExecutor-1F3
SimpleAsyncTaskExecutor-1F4
SimpleAsyncTaskExecutor-1F5
SimpleAsyncTaskExecutor-1F6
SimpleAsyncTaskExecutor-1F7
SimpleAsyncTaskExecutor-1F8
SimpleAsyncTaskExecutor-1F9
INFO [org.springframework.batch.core.job.SimpleStepHandler] - Executing step: [mysteps_flow_first]
SimpleAsyncTaskExecutor-1F0
SimpleAsyncTaskExecutor-1F1
SimpleAsyncTaskExecutor-1F2
SimpleAsyncTaskExecutor-1F3
SimpleAsyncTaskExecutor-1F4
SimpleAsyncTaskExecutor-1F5
SimpleAsyncTaskExecutor-1F6
SimpleAsyncTaskExecutor-1F7
SimpleAsyncTaskExecutor-1F8
SimpleAsyncTaskExecutor-1F9
INFO [org.springframework.batch.core.job.SimpleStepHandler] - Executing step: [mysteps_flow_second]
SimpleAsyncTaskExecutor-1S0
SimpleAsyncTaskExecutor-1S1
SimpleAsyncTaskExecutor-1S2
SimpleAsyncTaskExecutor-1S3
SimpleAsyncTaskExecutor-1S4
SimpleAsyncTaskExecutor-1S5
SimpleAsyncTaskExecutor-1S6
SimpleAsyncTaskExecutor-1S7
SimpleAsyncTaskExecutor-1S8
SimpleAsyncTaskExecutor-1S9
INFO [org.springframework.batch.core.job.SimpleStepHandler] - Executing step: [mysteps_flow_third]
SimpleAsyncTaskExecutor-1T0
SimpleAsyncTaskExecutor-1T1
SimpleAsyncTaskExecutor-1T2
SimpleAsyncTaskExecutor-1T3
SimpleAsyncTaskExecutor-1T4
SimpleAsyncTaskExecutor-1T5
SimpleAsyncTaskExecutor-1T6
SimpleAsyncTaskExecutor-1T7
SimpleAsyncTaskExecutor-1T8
SimpleAsyncTaskExecutor-1T9
INFO [org.springframework.batch.core.launch.support.SimpleJobLauncher] - Job: [FlowJob: [name=fJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]