和传统的批处理(Batch Processing)相比,Spring Batch虽然有很大的不同,但是归根结底,都是顺序地执行一些列任务。你用Spring Batch可以读取一个TXT文件的内容,然后将处理之后的数据放到数据库里,反之亦然。
Spring Batch任务处理的核心组件有Job、Step、Tasklet、JobLuncher和JobRepository等。其中,Job即每次批处理时需要完成的工作,一个Job可以包含多个Step,Step可以顺序执行,也可以通过配置分支性执行。Tasklet为相对独立的一个任务步骤,比如清空数据库、启动Web服务器等。JobLuncher用来运行一个Job,而JobRepository则用于完成Spring Batch本身的数据库访问,我们只需要配置好JobRepository就行了,至于数据库访问操作则又框架自动完成。
一般的批处理都是通过任务计划工具(Scheduler)来自动启动,比如Linux下的corn。对于Spring Batch,我们可以用Quartz和ControlM等任务计划工具来进行定时启动。
在用JobLuncher启动一个Job时,我们需要提供JobParameters。JobParameters的作用是一方面可以向Job提供一些参数,一方面可以用来标定Job的唯一性。比如,对于前者,你可以将日期参数传给Job,然后在Job中使用该日期从数据库中查询当天的数据记录;而对于后者,如果先后两次执行同一个Job时传入的参数一样,那么在第二次执行时,Spring Batch会抱怨“已经有一个相同的Job实例存在”,然后终止第二次Job的执行,所以在用JobLuncher执行Job时,我们需要提供不同的JobParameter来保证每次Job执行的唯一性。当然,JobParameters中可以包含多个参数,根据你自己的需要,有些参数可以在前后执行Job时保持一致,但是所有的JobParameters不能够全部相同。下面代码演示了如何执行一个Job:
HashMap<String, JobParameter> parameters = new HashMap<String, JobParameter>(); parameters.put("myParameter", new JobParameter("today")); JobParameters jobParameters = new JobParameters(parameters); jobLauncher.run(myJob, jobParameters);
对于通常的一些Step,我们都需要先读入一些数据,再写出一些数据。Spring Batch为我们提供了ItemReader和ItemWriter,配置如下:
<job id="myJob" xmlns="http://www.springframework.org/schema/batch"> <step id="simpleTaskletStep" next="simplePrintStep"> <tasklet> <chunk reader="itemReader" writer="itemWriter" commit-interval="2"/> </tasklet> </step> </job>
以上代码配置了一个名为myJob的Job,该Job中包含了一个Step,在该Step的tasklet中配置了一个itemReader和itemWriter。
ItemReader和ItemWriter均为均为接口,我们需要定义自己的reader和writer来分别实现这两个接口。当然,也可以使用Spring Batch现成提供的,比如JdbcCurcorItemReader。
一个Tasklet中的ItemReader和ItemWriter协同工作,基本原理是:ItemReader中read方法会被框架循环调用,直到read方法返回null为止。read返回的对象会自动的传给ItemWriter的write方法。ItemReader的read方法返回的一般为一个我们自己定义领域对象,而你会发现ItemWriter的write方法接受的并不是单个对象,而是一个List,这便和以上配置中的commit-interval有关系了。
举个例子,对已以上配置,commit-interval="2",表示框架首先会执行两次ItemReader的read方法,再将这两次分别返回的对象放到一个List里面,最后将该List传给ItemWriter。然后又重新执行read方法两次,将得到的List传给write方法。这样重复执行,知道read方法返回为null为止。
关于Spring Batch的例子,可以查看笔者的Github。