跳到主要内容
版本:5.2.1

TaskletStep

QWen Plus 中英对照 TaskletStep TaskletStep

块导向处理 并不是在 Step 中处理的唯一方式。如果一个 Step 必须由存储过程调用组成怎么办?你可以将该调用实现为一个 ItemReader,并在过程完成后返回 null。然而,这样做有些不自然,因为需要有一个无操作的 ItemWriter。Spring Batch 为此场景提供了 TaskletStep

Tasklet 接口有一个方法 execute,它会被 TaskletStep 反复调用,直到它返回 RepeatStatus.FINISHED 或抛出异常以指示失败。对 Tasklet 的每次调用都会被包装在一个事务中。Tasklet 的实现者可能会调用存储过程、脚本或 SQL 更新语句。

在 Java 中创建 TaskletStep 时,传递给构建器的 tasklet 方法的 bean 应实现 Tasklet 接口。在构建 TaskletStep 时不应调用 chunk 方法。以下示例展示了一个简单的 tasklet:

@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.tasklet(myTasklet(), transactionManager)
.build();
}
备注

如果它实现了 StepListener 接口,TaskletStep 会自动将任务块注册为 StepListener

TaskletAdapter

与其他 ItemReaderItemWriter 接口的适配器类似,Tasklet 接口也包含一个实现,允许其适配到任何现有的类:TaskletAdapter。一个可能有用的示例是,现有的 DAO 用于更新一组记录上的标志位。您可以使用 TaskletAdapter 调用此类,而无需为 Tasklet 接口编写适配器。

下面的示例展示了如何在 Java 中定义一个 TaskletAdapter

@Bean
public MethodInvokingTaskletAdapter myTasklet() {
MethodInvokingTaskletAdapter adapter = new MethodInvokingTaskletAdapter();

adapter.setTargetObject(fooDao());
adapter.setTargetMethod("updateFoo");

return adapter;
}

示例 Tasklet 实现

许多批处理作业包含一些步骤,这些步骤必须在主处理开始之前完成,以设置各种资源,或者在处理完成后清理这些资源。对于大量依赖文件操作的作业,在文件成功上传到其他位置后,通常需要删除本地的某些文件。以下示例(摘自 Spring Batch 示例项目)是一个 Tasklet 实现,其职责正是如此:

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(), "The resource must be a directory");

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.state(directory != null, "Directory must be set");
}
}

前面的 tasklet 实现会删除指定目录中的所有文件。需要注意的是,execute 方法只会被调用一次。接下来要做的就是从 step 中引用该 tasklet

下面的示例展示了如何在 Java 中从 step 引用 tasklet

@Bean
public Job taskletJob(JobRepository jobRepository, Step deleteFilesInDir) {
return new JobBuilder("taskletJob", jobRepository)
.start(deleteFilesInDir)
.build();
}

@Bean
public Step deleteFilesInDir(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("deleteFilesInDir", jobRepository)
.tasklet(fileDeletingTasklet(), transactionManager)
.build();
}

@Bean
public FileDeletingTasklet fileDeletingTasklet() {
FileDeletingTasklet tasklet = new FileDeletingTasklet();

tasklet.setDirectoryResource(new FileSystemResource("target/test-outputs/test-dir"));

return tasklet;
}