Spring Batch 2.1.8 中文文档(五)

3.2 Step

        Step是一个领域对象,它封装了批处理任务中的一个独立的连续阶段。因此每个job是由一个或是多个step组成的,step包含了定义以及控制一个实际运行中批处理任务所必须的所有信息。这个描述很含糊,是因为step中的内容完全是编写job的开发者所赋予的,step的复杂度完全依赖于开发者。一个简单的step可能只是从文件中加载数据到数据库,只需要几行代码(依赖于实现方式)。一个复杂的step可能作为整个业务处理的一部分而有着复杂的业务流程。像job那样,step有着自己的StepExecution并且对应于唯一一个JobExecution:

3.2.1 StepExecution

StepExecution表示需要执行一个step,和JobExecution类似,在每次运行step时会创建一个新的StepExecution。但是,如果一个Step之前的那个step执行失败导致这个step无法执行,则不会为这个step创建对应的StepExecution,因为StepExecution只会在step实际启动时创建。

Step的执行过程是由StepExecution类的对象所表示的,包括了每次执行所对应的step、JobExecution、相关的事务操作(例如提交与回滚)、开始时间结束时间等。此外每次执行step时还包含了一个ExecutionContext,用来存放开发者在批处理运行过程中所需要的任何信息,例如用来重启的静态数据与状态数据。下表列出了StepExecution的属性:

status使用BatchStatus对象来表示执行状态。运行时,状态为BatchStatus.STARTED;运行失败状态为BatchStatus.FAILED;成功结束时状态为BatchStatus.COMPLETED
startTime执行开始时间,使用java.util.Date表示
endTime执行结束时间(成功或失败),使用java.util.Date表示
exitStatus执行结果,使用ExitStatus表示。最重要的是它包含了返回给调用者的退出代码。查看第五章有更多细节。
executionContext包含了在执行过程中任何需要进行持久化的用户数据
readCount成功读取的记录数
writeCount成功写入的记录数
commitCount执行过程的事务中成功提交次数
rollbackCount执行过程的事务中回滚次数
readSkipCount因为读取失败而略过的记录数
processSkipCount因为处理失败而略过的记录数
filterCount被ItemProcessor过滤的记录数
writerSkipCount因为写入失败而略过的记录数

3.3 ExecutionContext

ExecutionContext是一组框架持久化与控制的key/value对,能够让开发者在StepExecution或JobExecution范畴保存需要进行持久化的状态,它同QuartZ的JobDataMap是相似的。任务重启就是最好的例子。以一个平面文件输入为例,在处理单行时,框架会在每次commit之后持久化ExecutionContext,这样ItemReader万一在运行过程中遇到问题,甚至是掉电,也能够存储之前的状态。而完成这些只需要把当前读取的行数放入context中,框架就会完成剩下的:

  1. executionContext.putLong(getKey(LINES_READ_COUNT), reader.getPosition());  
使用之前的EndOfDay例子,假设有这么一部:'loadData',从数据库中加载文件。在第一次失败后,元数据表应该是这样:

Table 3.9  BATCH_JOB_INSTANCE

JOB_INST_IDJOB_NAME
1EndOfDayJob

Table 3.10 BATCH_JOB_PARAMS

JOB_INST_IDTYPE_CDKEY_NAMEDATE_VAL
1DATEscheduler.Date2008-01-01

Table 3.11 BATCH_JOB_EXECUTION

JOB_EXEC_IDJOB_INST_IDSTART_TIMEEND_TIMESTATUS
112008-01-01 21:002008-01-01 21:30FAILED

Table 3.12 BATCH_STEP_EXECUTION

STEP_EXEC_IDJOB_EXEC_IDSTEP_NAMESTART_TIMEEND_TIMESTATUS
11loadDate2008-01-01 21:002008-01-01 21:30FAILED

Table 3.13 BATCH_STEP_EXECUTION_CONTEXT

STEP_EXEC_IDSHORT_CONTEXT
1{piece.count=40321}

在这个例子中,运行30分钟处理了40321条记录,框架在每次提交前会更新这个数字,并且ExecutionContext可以包含多个相关条目。如果要在提交前进行通知,还需要一个StepListener变量或是一个ItemStream变量,这个在随后的章节中会有更详细的讨论。就之前的这个例子,假定job在第二天重启,在重启时会从数据库中读取前一次运行保存下来的数据重组成ExecutionContext,打开ItemReader的时候,ItemReader会检查context中保存的状态并使用这些状态进行初始化:

  1. if (executionContext.containsKey(getKey(LINES_READ_COUNT))) {  
  2.     log.debug("Initializing for restart. Restart data is: " + executionContext);  
  3.   
  4.     long lineCount = executionContext.getLong(getKey(LINES_READ_COUNT));  
  5.   
  6.     LineReader reader = getReader();  
  7.   
  8.     Object record = "";  
  9.     while (reader.getPosition() < lineCount && record != null) {  
  10.         record = readLine();  
  11.     }  
  12. }  

在上面的代码执行完成后,记录下当前行是40322,这样下次启动时就能从这一行开始继续执行。ExecutionContext也能用来统计需要保存的运行内容,例如,一个文件需要处理订单,而一条订单可能保存为多行记录,此时需要记录处理了多少条订单(订单数与文件行数不同)并在任务处理完成后把处理的订单总数用邮件发送出去,框架会为开发者把这些数据记录到当前运行的这个JobInstance的scope中。另外,判断ExecutionContext的使用时机是比较困难的。例如使用上面的'EndOfDay'例子,当01-01任务在01-02再次运行时,框架会认识到这是一个相同的JobInstance中一个不同的Step,于是从数据库中取出ExecutionContext作为Step的一部分StepExecution内容;相反对于01-02任务框架要认识到这是一个不同的instance,于是会给step一个空的context。框架需要为工程师做各种判断以保证在准确的时间有准确的状态。还需要重视的是在任何时间对于每个StepExecution只有一个ExecutionContext,因为创建的是一个共有的keyspace,ExecutionContext的客户端需要小心放置key-value数据以确保没有数据被覆盖。当然如果step没有在Context中保存数据,自然也不会被框架造成不利的影响。

一个JobExecution至少有一个ExecutionContext,所有StepExecution共用一个ExecutionContext。像代码所示:

  1. ExecutionContext ecStep = stepExecution.getExecutionContext();  
  2. ExecutionContext ecJob = jobExecution.getExecutionContext();  
  3. //ecStep does not equal ecJob  

ecStep不等于ecJob,他们是两个不同的ExecutionContext。step范围的ExecutionContext在Step被提交时保存,job范围的ExecutionContext在两个step执行之间保存。

3.4 JobRepository

JobRepository是上面所有概念的持久化机制,为JobLauncher,Job和Step提供了CRUD实现。当一个Job第一次启动时,从仓库中获取一个JobExecution,之后在整个执行过程中StepExecution和JobExecution都被这样持久化到仓库中:

  1. <job-repository id="jobRepository"/>  


3.5 JobLauncher

JobLauncher是使用取得的参数启动Job的简单接口:

  1. public interface JobLauncher {  
  2.   
  3.     public JobExecution run(Job job, JobParameters jobParameters)   
  4.                 throws JobExecutionAlreadyRunningException, JobRestartException;  
  5. }  

此处希望从JobRepository获取一个合法的JobExecution并执行之。

3.6 Item Reader

ItemReader是一个抽象概念,用于表示step读取数据,一次读取一条。当ItemReader读完了所有数据,它会返回一个null值。更多的细节可以参考"Chapter 6 ItemReader and ItemWriter"。

3.7 Item Writer

ItemWriter是一个抽象概念,用于表示step输出数据,一次输出一批。通常情况下,ItemWriter只有在数据进入ItemWriter时,才知道输入的数据内容。更多细节可以参考"Chapter 6 ItemReader and ItemWriter"。

3.8 Item Processor

ItemProcessor是一个抽象概念,用于表示item的业务处理。ItemReader读数据,ItemWriter写数据,ItemProcessor能够转换数据或是处理业务逻辑。如果在处理过程中数据不合法,则会返回null值表示数据没有输出。更多细节可以参考"Chapter 6 ItemReader and ItemWriter"。

3.9 Batch Namespace

上面的许多领域概念都需要在spring的ApplicationContext中配置。但是如果这些接口的实现使用标准的bean定义,那么namespace提供了更容易的配置方式:

  1. <beans:beans xmlns="http://www.springframework.org/schema/batch"   
  2.      xmlns:beans="http://www.springframework.org/schema/beans"   
  3.      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.      xsi:schemaLocation="  
  5.            http://www.springframework.org/schema/beans   
  6.            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.            http://www.springframework.org/schema/batch   
  8.            http://www.springframework.org/schema/batch/spring-batch-2.0.xsd">  
  9.   
  10.     <job id="ioSampleJob">  
  11.         <step id="step1">  
  12.             <tasklet>  
  13.                 <chunk reader="itemReader" writer="itemWriter" commit-interval="2"/>  
  14.             </tasklet>  
  15.         </step>  
  16.     </job>  
  17.   
  18. </beans:beans>  

只要批处理的namespace申明过,那么这些元素就能够使用。更多配置job的信息参考"Chapter4 Configuring and Running a Job。更多配置step的信息参考"Chapter 5,Configuring a Step"。


http://blog.csdn.net/shorn/article/details/7925935

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值