|
| 1 | +# 4.1 Configuring a Job |
| 2 | + |
| 3 | + [Job接口](http://docs.spring.io/spring-batch/trunk/reference/html/configureJob.html) 的实现有多个,但是在配置上命名空间存在着不同。必须依赖的只有三项:名称 **name**,**JobRespository** 和 **Step** 的列表: |
| 4 | + |
| 5 | + <job id="footballJob"> |
| 6 | + <step id="playerload" parent="s1" next="gameLoad"/> |
| 7 | + <step id="gameLoad" parent="s2" next="playerSummarization"/> |
| 8 | + <step id="playerSummarization" parent="s3"/> |
| 9 | + </job> |
| 10 | + |
| 11 | +在这个例子中使用了父类的bean定义来创建step,更多描述step配置的信息可以参考[step configuration](http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html)这一节。XML命名空间默认会使用id为'jobRepository'的引用来作为repository的定义。然而可以向如下显式的覆盖: |
| 12 | + |
| 13 | + <job id="footballJob" job-repository="specialRepository"> |
| 14 | + <step id="playerload" parent="s1" next="gameLoad"/> |
| 15 | + <step id="gameLoad" parent="s3" next="playerSummarization"/> |
| 16 | + <step id="playerSummarization" parent="s3"/> |
| 17 | + </job> |
| 18 | + |
| 19 | +此外,job配置的step还包含其他的元素,有并发处理(<split/>),显示的流程控制(<decision/>)和外化的流程定义(<flow/>)。 |
| 20 | + |
| 21 | +## 4.1.1 Restartablity ## |
| 22 | + |
| 23 | +执行批处理任务的一个关键问题是要考虑job被重启后的行为。如果一个 **JobExecution** 已经存在一个特定的 **JobInstance** ,那么这个job启动时可以认为是“重启”。 理想情况下,所有任务都能够在他们中止的地方启动,但是有许多场景这是不可能的。在这种场景中就要有开发者来决定创建一个新的 **JobInstance** ,Spring对此也提供了一些帮助。如果job不需要重启,而是总是作为新的 **JobInstance** 来运行,那么可重启属性可以设置为'false': |
| 24 | + |
| 25 | + <job id="footballJob" restartable="false"> |
| 26 | + ... |
| 27 | + </job> |
| 28 | + |
| 29 | +设置重启属性restartable为‘false’表示‘这个job不支持再次启动’,重启一个不可重启的job会抛出JobRestartException的异常: |
| 30 | + |
| 31 | + Job job = new SimpleJob(); |
| 32 | + job.setRestartable(false); |
| 33 | + |
| 34 | + JobParameters jobParameters = new JobParameters(); |
| 35 | + |
| 36 | + JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters); |
| 37 | + jobRepository.saveOrUpdate(firstExecution); |
| 38 | + |
| 39 | + try { |
| 40 | + jobRepository.createJobExecution(job, jobParameters); |
| 41 | + fail(); |
| 42 | + } |
| 43 | + catch (JobRestartException e) { |
| 44 | + //预计抛出JobRestartException异常 |
| 45 | + } |
| 46 | + |
| 47 | +这个JUnit代码展示了创建一个不可重启的Job后,第一次能够创建 **JobExecution** ,第二次再创建相同的JobExcution会抛出一个 **JobRestartException**。 |
| 48 | + |
| 49 | + |
| 50 | +## 4.1.2 Intercepting Job Execution ## |
| 51 | + |
| 52 | +在job执行过程中,自定义代码能够在生命周期中通过事件通知执行会是很有用的。SimpleJob能够在适当的时机调用JobListener: |
| 53 | + |
| 54 | + public interface JobExecutionListener { |
| 55 | + |
| 56 | + void beforeJob(JobExecution jobExecution); |
| 57 | + |
| 58 | + void afterJob(JobExecution jobExecution); |
| 59 | + |
| 60 | + } |
| 61 | + |
| 62 | +JobListener能够添加到SimpleJob中去,作为job的listener元素: |
| 63 | + |
| 64 | + <job id="footballJob"> |
| 65 | + <step id="playerload" parent="s1" next="gameLoad"/> |
| 66 | + <step id="gameLoad" parent="s2" next="playerSummarization"/> |
| 67 | + <step id="playerSummarization" parent="s3"/> |
| 68 | + <listeners> |
| 69 | + <listener ref="sampleListener"/> |
| 70 | + </listeners> |
| 71 | + </job> |
| 72 | + |
| 73 | +无论job执行成功或是失败都会调用afterJob,都可以从 **JobExecution** 中获取运行结果后,根据结果来进行不同的处理: |
| 74 | + |
| 75 | + public void afterJob(JobExecution jobExecution){ |
| 76 | + if( jobExecution.getStatus() == BatchStatus.COMPLETED ){ |
| 77 | + //job执行成功 } |
| 78 | + else if(jobExecution.getStatus() == BatchStatus.FAILED){ |
| 79 | + //job执行失败 } |
| 80 | + } |
| 81 | + |
| 82 | +对应于这个interface的annotation为: |
| 83 | + |
| 84 | +- @BeforeJob |
| 85 | +- @AfterJob |
| 86 | + |
| 87 | +## 4.1.3 Inheriting from a parent Job ## |
| 88 | + |
| 89 | +如果一组job配置共有相似,但又不是完全相同,那么可以定义一个"父”job,让这些job去继承属性。同Java的类继承一样,子job会把父job的属性和元素合并进来。 |
| 90 | + |
| 91 | +下面的例子中,“baseJob”是一个抽象的job定义,只定义了一个监听器列表。名为“job1”的job是一个具体定义,它继承了“baseJob"的监听器,并且与自己的监听器合并,最终生成的job带有两个监听器,以及一个名为”step1“的step。 |
| 92 | + |
| 93 | + <job id="baseJob" abstract="true"> |
| 94 | + <listeners> |
| 95 | + <listener ref="listenerOne"/> |
| 96 | + <listeners> |
| 97 | + </job> |
| 98 | + |
| 99 | + <job id="job1" parent="baseJob"> |
| 100 | + <step id="step1" parent="standaloneStep"/> |
| 101 | + |
| 102 | + <listeners merge="true"> |
| 103 | + <listener ref="listenerTwo"/> |
| 104 | + <listeners> |
| 105 | + </job> |
| 106 | + |
| 107 | +更多信息可参见 [Inheriting from a Parent Step](http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html#InheritingFromParentStep) |
| 108 | + |
| 109 | + |
| 110 | +## 4.1.4 JobParametersValidator ## |
| 111 | + |
| 112 | +一个在xml命名空间描述的job或是使用任何抽象job子类的job,可以选择为运行时为job参数定义一个验证器。在job启动时需要保证所有必填参数都存在的场景下,这个功能是很有用的。有一个DefaultJobParametersValidator可以用来限制一些简单的必选和可选参数组合,你也可以实现接口用来处理更复杂的限制。验证器的配置支持使用xml命名空间来作为job的子元素,例如: |
| 113 | + |
| 114 | + <job id="job1" parent="baseJob3"> |
| 115 | + <step id="step1" parent="standaloneStep"/> |
| 116 | + <validator ref="paremetersValidator"/> |
| 117 | + </job> |
| 118 | + |
| 119 | +验证器可以作为一个引用(如上)来定义也可以直接内嵌定义在bean的命名空间中。 |
0 commit comments