跳到主要内容

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();
}
java
备注

如果它实现了 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;
}
java

示例 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");
}
}
java

前面的 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;
}
java