针对我们的实践中,我们可以使用 Tasklet 来执行一个 FTP 的任务。

将我们产生的中间文件上传到不同的 FTP 服务器上,你可以在实现中指定不同的服务器配置参数,这样更加有利于代码的重用。

为了能够创建一个 TaskletStep,Bean 需要传递一个 tasklet 方法到构造器(builder),这个 tasklet 方法需要实现 Tasklet 接口。

当你构建 TaskletStep 的时候不要调用 chunk

下面的示例代码显示了一个在 Step build 中构建一个简单的 tasklet。

@Beanpublic Step step1() {return this.stepBuilderFactory.get("step1").tasklet(myTasklet()).build();}

如果你的 tasklet 实现了 StepListener 接口的话,TaskletStep 将会自动将 tasklet 注册成为一个 StepListener

TaskletAdapter

ItemReader ItemWriter 接口的 adapters一样。Tasklet 接口包含的实现也允许能够通过已经存在的类使用 TaskletAdapter 来将自己进行注册。

例如,你希望使用一个已经存在的 DAO 来更新记录集上的标记的时候,你可以使用 TaskletAdapter 来进行实现。

使用 TaskletAdapter 能够让你的 DAO 可以被 Spring Batch 的 TaskletStep 调用而不需要让你的 DAO 都实现 Tasklet 的接口。

如下面的示例代码:

@Beanpublic MethodInvokingTaskletAdapter myTasklet() {MethodInvokingTaskletAdapter adapter = new MethodInvokingTaskletAdapter();adapter.setTargetObject(fooDao());adapter.setTargetMethod("updateFoo");return adapter;}Tasklet 实现(Implementation)示例

在主批量作业开始之前,可能需要很多其他的批量作业必须完成,这样以便于主批量作业能够获得必要的资源和在完成后释放资源或者进行清理。

例如我们遇到下面的使用场景,一个批量作业需要大量的对文件进行交互和使用,通常来说需要在文件被上传到其他服务器上后删除本地产生的临时文件。

下面的示例就是一个 Tasklet 的实现,这个Tasklet 的实现能够完成上面的交互要求(文件来自 Spring Batch samples project 示例程序)。

public class FileDeletingTasklet implements Tasklet, InitializingBean {private Resource directory;public RepeatStatus execute(StepContribution contribution,ChunkContext chunkContext) throws Exception {File dir = directory.getFile();Assert.state(dir.isDirectory());File[] files = dir.listFiles();for (int i = 0; i < files.length; i++) {boolean deleted = files[i].delete();if (!deleted) {throw new UnexpectedJobExecutionException("Could not delete file " +files[i].getPath());}}return RepeatStatus.FINISHED;}public void setDirectoryResource(Resource directory) {this.directory = directory;}public void afterPropertiesSet() throws Exception {Assert.notNull(directory, "directory must be set");}}

Tasklet 处理程序实现了将给定目录中的所有文件进行删除。我们应该通知 execute 方法,这个 Tasklet 应该只被执行一次。

所有相关执行的操作需要在 Step 中进行设置,请参考下面有关这个 Tasklet 的设置:

Java 配置

@Beanpublic Job taskletJob() {return this.jobBuilderFactory.get("taskletJob").start(deleteFilesInDir()).build();}@Beanpublic Step deleteFilesInDir() {return this.stepBuilderFactory.get("deleteFilesInDir").tasklet(fileDeletingTasklet()).build();}@Beanpublic FileDeletingTasklet fileDeletingTasklet() {FileDeletingTasklet tasklet = new FileDeletingTasklet();tasklet.setDirectoryResource(new FileSystemResource("target/test-outputs/test-dir"));return tasklet;}