spring batch(二):核心部分(1):配置Spring batch
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:batch="http://www.springframework.org/schema/batch"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/batchhttp://www.springframework.org/schema/batch/spring-batch.xsd"><batch:job id="importProductsJob">(...)</batch:job></beans>
?
?
当指定batch命名空间之后,bean中的声明都需要加上batch的前缀,例如:<batch:job id="importProductsJob">
spring的命名空间的前缀可以指定任意的名称,这里采用batch作为前缀,为了方便理解。
?
2、spring batch XML的主要标签有:job、step、tasklet、chunk、job-repository
3、Job配置。job元素是整个配置的顶级元素,它的属性有:
a、id
b、restartable
c、incrementer
d、abstract
e、parent
f、job-repository
?
restartable 属性如果是false,则程序不允许重启。如果发生重启,会抛出JobRestartException异常。
?
<batch:job id="importProductsJob" restartable="false"> (...)</batch:job>
?job除了这些属性外,还可以配置验证器<batch:validator ref="parameterValidator" />,用来校验工作参数(job parameters),可以实现JobParametersValidator接口。
如果无法通过验证,会抛出JobParametersInvalidException异常。spring batch提供了一个默认的实现类DefaultJobParametersValidator,完成绝大部分的工作。如果还是无法满足需求,可以自己编码实现接口。
实例:
?
<batch:job id="importProductsJob">(...)<batch:validator ref="validator"/></batch:job><bean id="validator" name="code"><job id="importProductsJob"><step id="decompress" next="readWrite">(...)</step><step id="readWrite">(...)</step></job>
?
5、tasklet和chunk的配置。
tasklet和chunk是用来指定处理过程的。
一个tasklet对应于一个事务性的、潜在可重复的过程中发生的一个步骤。
你可以自己实现Tasklet 接口,定义自己的tasklet。这个特性很有用,比如:用于解压文件,执行系统命令,执行存储过程等待。
你也可以使用系统tasklet的属性有:
a、ref指定应用的bean
b、transaction-manager事物管理器
c、start-limittasklet重试retry的次数
d、allow-start-if-complete如果tasklet成功完成之后,是否可以进行重试retry操作。
示例:
?
<batch:job id="importProductsJob">(...)<batch:step id="readWriteStep"><batch:tasklettransaction-manager="transactionManager"start-limit="3"allow-start-if-complete="true">(...)</batch:tasklet></batch:step></batch:job><bean id="transactionManager" name="code"><batch:job id="importProductsJob">(...)<batch:step id="readWrite"><batch:tasklet><batch:chunkreader="productItemReader"processor="productItemProcessor"writer="productItemWriter"commit-interval="100" skip-limit="20"retry-limit="3"cache-capacity="100"chunk-completion-policy="timeoutCompletionPolicy"/></batch:tasklet></batch:step></batch:job><bean id="productItemReader" name="code"><batch:job id="importProductsJob">(...)<batch:step id="readWrite"><batch:tasklet><batch:chunk commit-interval="100"><batch:reader><bean name="code"><batch:job id="importProductsJob">(...)<batch:step id="readWrite"><batch:tasklet><batch:chunk commit-interval="100"skip-limit="10"><skippable-exception-classes><include name="code"><batch:job id="importProductsJob">(...)<batch:step id="readWrite"><batch:tasklet><batch:chunk reader="productItemReader" writer="compositeWriter"/><streams><stream ref="productItemWriter1"/><stream ref="productItemWriter2"/></streams></batch:tasklet></batch:step></batch:job><bean id="compositeWriter"name="code"><batch:job id="importProductsJob">(...)<batch:step id="readWrite"><batch:tasklet transaction-manager="transactionManager" (...)>(...)</batch:tasklet></batch:step></batch:job>
?事务,有几个定义的属性:行为,隔离 isolation,超时 timeout。
spring batch提供transaction-attributes标签来描述这些事务的属性。
?示例:
<batch:tasklet><batch:chunk reader="productItemReader"writer="productItemReader"commit-interval="100"/><batch:transaction-attributes isolation="DEFAULT"propagation="REQUIRED"timeout="30"/></batch:chunk></batch:tasklet>
?isolation 定义数据库的隔离级别以及对外部事务的可见性。
spring的事务处理是基于java的异常体系的。java里面的异常分为两类:检查型异常(extends Exception)和非检查型异常(extends RuntimeException)
spring对检查型异常进行commit提交处理,对非检查型异常进行rollback回滚处理。
spring batch运行你对不需要触发rollback回滚动作的异常进行定义。你可以在tasklet的no-rollback-exception-class元素中进行指定。
?示例:
<batch:tasklet>(...)<batch:no-rollback-exception-classes><batch:includename="code"><bean id="jobRepository" ref="transactionManager"/></bean><bean id="transactionManager"name="code"><bean id="dataSource"value="${batch.jdbc.driver}" /><property name="url" value="${batch.jdbc.url}" /><property name="username" value="${batch.jdbc.user}" /><property name="password" value="${batch.jdbc.password}" /></bean><bean id="transactionManager" lazy-init="true"ref="dataSource" /></bean><batch:job-repository id="jobRepository"data-source="dataSource"transaction-manager="transactionManager"isolation-level-for-create="SERIALIZABLE"table-prefix="BATCH_"/><batch:job id="importInvoicesJob" job-repository="jobRepository">(...)</batch:job>?[问题:如果在不同的物理节点上面运行同样的job会发生什么呢?]
前提:使用同一份spring batch的元数据,即采用同一份数据库上面的表结构。
当创建job实例和执行信息的元数据的时候,job仓库扮演了一个集中维护的工作库的角色。当job并发运行的时候,spring batch 的job仓库,可以防止创建相同的工作情况。这个功能依赖于底层数据库的事务能力,完成job的同步任务。我们设置job仓库的属性isolation-level-for-create="SERIALIZABLE",来避免发生job的并发问题。由于有这种防护措施,你可以把你的spring batch的job分布到各个不同的物理节点,保证你的job实例不会被创建两次。
? ? ?job仓库是spring batch底层结构中的重要部分,它记录了batch处理的信息,并且跟踪job运行的成功与失败。
?
?8、spring batch配置的高级主题。
(1)、使用step作用域。当使用SpEL的时候,step作用域很有用,来实现属性的晚绑定。
(2)、Spring表达式语言:Spring Expression Language (SpEL)?
Spring3.× 开始提供。
?step的作用的实例范围包括:jobParameters、jobExecutionContext、stepExecutionContext
?示例:
?
<bean id="decompressTasklet"/><property name="targetDirectory"value="#{jobParameters['targetDirectory']}" /><property name="targetFile"value="#{jobParameters['targetFile']}" /></bean>?SpEL由?#{ 和 } 组成
?
?在jobExecutionContext 和 stepExecutionContext也可以应用SpEL表达式。
?(3)、使用Linteners提供的更多的处理。
Spring batch在job和step级别上面提供listener。
Spring batch提供的listener的类型:
a、Job listener:在job级别监听处理过程
b、Step listeners:在step级别监听处理过程
c、Item listeners:监听item的retry重试和repeat重做动作
一、Job listener 可以监听job的运行,在job运行前和后添加动作。可以利用 listener标签,在job标签下面作为子元素进行添加。
示例1:
?
<batch:job id="importProductsJob"><batch:listeners><batch:listener ref="importProductsJobListener"/></batch:listeners></batch:job>
?importProductsJobListener不管job运行成功还是失败,它都会在job运行的开始和结束的时候,接收job的通知,进行监听。
?
?
还可以通过普通的POJO的java对象来做监听器,只需要进行简单的配置即可。
示例2:
?
<batch:listeners> <batch:listener ref="importProductsJobListener" after-job-method="afterJob" before-job-method="beforeJob"/></batch:listeners>
?可以在listener里面的ref指定引用的POJO的bean,通过after-job-method="afterJob" before-job-method="beforeJob" 来指定job之前和之后的执行方法。不过,被指定的这两个方法的参数都需要是:JobExecution jobExecution。 这个2个方法的返回值都是void
?
还有一种方法是利用“注释”来配置listener,spring batch会自己发现并运行该类。
?
二、Step listener
? ? Step有一系列的listener来跟踪step的处理过程。这里所有的listener接口都继承了StepListener接口。
Spring batch提供的Step的listener有:
a、ChunkListener:在chunk执行的之前和之后调用。
b、ItemProcessListener:在?ItemProcessor得到一个item之前和之后调用,在ItemProcessor抛出一个异常的时候调用。
c、ItemReadListener:在读取item之前和读取item之后调用,或者在读取item的过程中触发异常的时候调用。
d、ItemWriteListener:在一个item输出之前和之后调用,或者在item输出的过程中调用。
e、SkipListener:当读取、处理和输出的过程中产生了skip跳跃一个item的时候调用。
f、StepExecutionListener:在step运行之前和之后调用。
?接口代码:
public interface StepExecutionListener extends StepListener {void beforeStep(StepExecution stepExecution);ExitStatus afterStep(StepExecution stepExecution);}public interface ChunkListener extends StepListener {void beforeChunk();void afterChunk();}public interface ItemProcessListener<T, S> extends StepListener {void beforeProcess(T item);void afterProcess(T item, S result);void onProcessError(T item, Exception e);}public interface ItemReadListener<T> extends StepListener {void beforeRead();void afterRead(T item);void onReadError(Exception ex);}public interface ItemWriteListener<S> extends StepListener {void beforeWrite(List<? extends S> items);void afterWrite(List<? extends S> items);void onWriteError(Exception exception, List<? extends S> items);}public interface SkipListener<T,S> extends StepListener {void onSkipInRead(Throwable t);void onSkipInProcess(T item, Throwable t);void onSkipInWrite(S item, Throwable t);}?Step listener 作为tasklet标签的一个子标签进行配置。
?上面这些所有的Step listener都可以作为tasklet标签的子标签以相同的方式和等级进行配置。
示例:
<bean id="importProductsJobListener"/><bean id="productStepExecutionListener"/><bean id="productChunkListener"/><bean id="productItemProcessListener"/><batch:job id="importProducts" restartable="false"><batch:step id="readWriteProducts"><batch:tasklet><batch:chunk reader="reader" writer="writer" processor="processor"commit-interval="100" skip-limit="5"><batch:skippable-exception-classes><batch:include/></batch:skippable-exception-classes></batch:chunk><batch:listeners><!-- here configure three kinds listeners for StepExecutionListener , ChunkListener , ItemProcessListener for example.--><batch:listener ref="productStepExecutionListener" /><batch:listener ref="productChunkListener" /><batch:listener ref="productItemProcessListener" /></batch:listeners></batch:tasklet></batch:step><batch:validator ref="parameterValidator" /><batch:listeners><batch:listener ref="importProductsJobListener" /></batch:listeners></batch:job>
?
?三、retry重试和repeat重做的listener
repeat listener拥有的方法名称:before、after、close(在一个item最后一次repeat重做之后调用,不管repeat成功与否)、onError、open
retry listener拥有的方法名称:close(在一个item上面最后一次尝试retry之后调用,不管retry成功与否)、onError、open
接口代码:
public interface RepeatListener {void before(RepeatContext context);void after(RepeatContext context, RepeatStatus result);void open(RepeatContext context);void onError(RepeatContext context, Throwable e);void close(RepeatContext context);}public interface RetryListener {<T> void open(RetryContext context, RetryCallback<T> callback);<T> void onError(RetryContext context,RetryCallback<T> callback, Throwable e);<T> void close(RetryContext context,RetryCallback<T> callback, Throwable e);}?这2个接口,和上面的step listener的配置位置和方式一致,都是tasklet标签的子标签位置
?
四、配置继承关系
spring的XML提供配置的继承。使用abstract和parent两个属性。从一个parent的bean继承,表示该bean可以利用parent bean中的所有的属性,并且可以覆盖这些属性。
示例:
<bean id="parentBean" abstract="true"><property name="propertyOne" value="(...)"/></bean><bean id="childBean" parent="parentBean"><property name="propertyOne" value="(...)"/><property name="propertyTwo" value="(...)"/></bean>
?这种继承关系是由spring提供的,在spring batch里面也可以使用。
listeners标签,提供merge属性,可以用来合并parent和自身的listener
?示例:
<job id="parentJob" abstract="true"><listeners><listener ref="globalListener"/><listeners></job><job id="importProductsJob" parent="parentJob">(...)<listeners merge="true"><listener ref="specificListener"/><listeners></job>
?spring XML的这种继承关系,使得spring batch的XML配置更简单。
?
?