跳到主要内容
版本:6.0.2

TaskletStep

DeepSeek V3 中英对照 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 会自动将 tasklet 注册为 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;
}