Spring Batch 5.2 的新特性

依赖升级

在此版本中,Spring 依赖项升级到以下版本

  • Spring Framework 6.2.0

  • Spring Integration 6.4.0

  • Spring Data 3.4.0

  • Spring Retry 2.0.10

  • Spring LDAP 3.2.8

  • Spring AMQP 3.2.0

  • Spring Kafka 3.3.0

  • Micrometer 1.14.1

支持 MongoDB 作业仓库

此版本引入了首个由 MongoDB 支持的 NoSQL 作业仓库实现。与关系型作业仓库实现类似,Spring Batch 提供了一个脚本用于在 MongoDB 中创建必要的集合,以保存和检索批处理元数据。

此实现需要 MongoDB 4 或更高版本,并基于 Spring Data MongoDB。要使用此作业仓库,您只需定义一个 MongoTemplate 和一个 MongoTransactionManager,它们是新增的 MongoJobRepositoryFactoryBean 所需的。

@Bean
public JobRepository jobRepository(MongoTemplate mongoTemplate, MongoTransactionManager transactionManager) throws Exception {
	MongoJobRepositoryFactoryBean jobRepositoryFactoryBean = new MongoJobRepositoryFactoryBean();
	jobRepositoryFactoryBean.setMongoOperations(mongoTemplate);
	jobRepositoryFactoryBean.setTransactionManager(transactionManager);
	jobRepositoryFactoryBean.afterPropertiesSet();
	return jobRepositoryFactoryBean.getObject();
}

定义了 MongoDB 作业仓库后,您可以将其作为常规作业仓库注入到任何作业或步骤中。您可以在 MongoDBJobRepositoryIntegrationTests 中找到完整的示例。

新的无资源作业仓库

在 v5 中,出于多种原因,基于 Map 的内存作业仓库实现被移除。Spring Batch 中唯一剩余的作业仓库实现是 JDBC 实现,它需要一个数据源。虽然这与 H2 或 HSQLDB 等内存数据库配合良好,但对于许多习惯于使用基于 Map 的仓库而无需额外依赖的社区用户来说,要求提供数据源是一个强烈的限制。

在此版本中,我们引入了一个 JobRepository 实现,它不使用或存储任何形式的批处理元数据(甚至不在内存中)。它是一个“无操作”(NoOp)实现,会丢弃批处理元数据且不与任何资源交互(因此得名“无资源作业仓库”,借鉴自“无资源事务管理器”)。

此实现适用于不需要重启以及执行上下文未以任何方式参与的用例(例如,通过执行上下文在步骤之间共享数据,或在分区步骤中通过执行上下文在管理器和工作节点之间共享分区元数据等)。

此实现适用于在自己的 JVM 中执行的一次性作业。它适用于事务性步骤(例如,使用 DataSourceTransactionManager 配置)以及非事务性步骤(使用 ResourcelessTransactionManager 配置)。此实现非线程安全,不应在任何并发环境中使用。

复合 Item Reader 实现

CompositeItemProcessorCompositeItemWriter 类似,我们引入了一个新的 CompositeItemReader 实现,旨在按顺序从具有相同格式的多个源读取数据。当数据分散在不同的资源中且编写自定义 Reader 不可行时,这非常有用。

CompositeItemReader 的工作方式与其他复合制品类似,通过按顺序将读取操作委托给常规 Item Reader。这是一个快速示例,展示了一个复合 Reader,它首先从平面文件读取人员数据,然后从数据库表读取。

@Bean
public FlatFileItemReader<Person> itemReader1() {
    return new FlatFileItemReaderBuilder<Person>()
            .name("personFileItemReader")
            .resource(new FileSystemResource("persons.csv"))
            .delimited()
            .names("id", "name")
            .targetType(Person.class)
            .build();
}

@Bean
public JdbcCursorItemReader<Person> itemReader2() {
    String sql = "select * from persons";
    return new JdbcCursorItemReaderBuilder<Person>()
            .name("personTableItemReader")
            .dataSource(dataSource())
            .sql(sql)
            .beanRowMapper(Person.class)
            .build();
}

@Bean
public CompositeItemReader<Person> itemReader() {
    return new CompositeItemReader<>(Arrays.asList(itemReader1(), itemReader2()));
}

新的 java.util.function API 适配器

与将 java.util.function.Function 适配为 Item Processor 的 FucntionItemProcessor 类似,此版本为其他 java.util.function 接口(如 SupplierConsumerPredicate)引入了几个新的适配器。

新增的适配器包括:SupplierItemReaderConsumerItemWriterPredicateFilteringItemProcessor。有关这些新适配器的更多详细信息,请参阅 org.springframework.batch.item.function 包。

使用阻塞队列 Item Reader 和 Writer 实现并发步骤

分阶段事件驱动架构 (SEDA) 是一种强大的架构风格,用于在通过队列连接的阶段中处理数据。由于 Spring Batch 能够将作业设计为一系列步骤,这种风格可以直接应用于数据管道并轻松实现。

这里唯一缺少的部分是如何从中间队列读取数据并向其写入数据。此版本引入了一个 Item Reader 和一个 Item Writer,用于从 BlockingQueue 读取数据并向其写入。有了这两个新类,可以设计第一个步骤将数据准备到队列中,然后设计第二个步骤从同一队列消费数据。这样,两个步骤可以并发运行,以非阻塞、事件驱动的方式高效处理数据。

JPA Item Reader 中的查询提示支持

在 5.1 版本之前,JPA 游标和分页 Item Reader 不支持查询提示(如 fetch size、timeout 等)。用户需要提供自定义查询提供程序来指定自定义提示。

在此版本中,JPA Reader 及其各自的构建器已更新,以在定义要使用的 JPA 查询时接受查询提示。

JDBC Item Reader 中的数据类支持

此版本在 JDBC 游标和分页 Item Reader 的构建器中引入了一个新方法,允许用户在项目类型为数据类(Java Record 或 Kotlin Data Class)时指定 DataClassRowMapper

新方法 dataRowMapper(TargetType.class)beanRowMapper(TargetType.class) 类似,旨在使常规类(Java Bean)和数据类(Java Record)之间的行映射器配置保持一致。

RecursiveCollectionLineAggregator 中可配置的行分隔符

到目前为止,RecursiveCollectionLineAggregator 中的行分隔符属性一直设置为系统的行分隔符值。虽然可以通过系统属性更改该值,但这种配置方式与批处理制品的其他属性不一致。

此版本在 RecursiveCollectionLineAggregator 中引入了一个新的 setter,允许用户配置自定义的行分隔符值,而无需使用系统属性。

作业注册改进

在 5.1 版本中,批处理基础设施 Bean 的默认配置已更新,通过在应用程序上下文中定义 JobRegistryBeanPostProcessor Bean 来自动填充作业注册表。在 Spring Framework 中最近对 BeanPostProcessorChecker 的日志级别进行了更改后,典型的 Spring Batch 应用程序会记录与 JobRegistryBeanPostProcessor 相关的多个警告。这些警告是由于 JobRegistryBeanPostProcessorJobRegistry Bean 存在依赖,这是不推荐的,并且可能导致 Bean 生命周期问题。

这些问题在此版本中已通过更改填充 JobRegistry 的机制得到解决,从使用 BeanPostProcessor 改为使用 SmartInitializingSingletonJobRegistryBeanPostProcessor 现已被弃用,推荐使用新增的 JobRegistrySmartInitializingSingleton