|
对于最新稳定版本,请使用 Spring Batch 文档 6.0.3! |
Spring Batch 5.2 的新功能
本节重点介绍 Spring Batch 5.2 中的主要变更。完整变更列表请参阅 发布说明。
Spring Batch 5.2 包含以下功能:
依赖项升级
在此版本中,Spring 依赖已升级到以下版本:
-
Spring 框架 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)。
该实现不是线程安全的,不应在任何并发环境中使用。
复合项读取器实现
类似于 CompositeItemProcessor 和 CompositeItemWriter,我们引入了一种新的 CompositeItemReader 实现,
旨在从多个具有相同格式的源中顺序读取数据。当数据分散在不同资源上且无法编写自定义读取器时,这非常有用。
CompositeItemReader 的工作方式与其他复合构件类似,它会按顺序将读取操作委托给常规的物品读取器。下面是一个快速示例,展示了一个复合读取器,它先从平面文件读取人员数据,再从数据库表中读取:
@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 适配为项处理器的 FunctionItemProcessor,此版本引入了针对其他 java.util.function 接口(如 Supplier、Consumer 和 Predicate)的多个新适配器。
新增的适配器有:SupplierItemReader、ConsumerItemWriter 和 PredicateFilteringItemProcessor。
有关这些新适配器的更多详细信息,请参阅 org.springframework.batch.item.function 包。
使用阻塞队列项读取器和写入器的并发步骤
分阶段事件驱动架构(SEDA)是一种强大的架构风格,用于通过队列连接各个阶段来处理数据。这种风格直接适用于数据管道,并且由于能够将作业设计为步骤序列,因此在 Spring Batch 中易于实现。
此处唯一缺失的部分是如何从中间队列读取数据以及向其中写入数据。此版本引入了一项读取器和一项写入器,用于从 BlockingQueue 读取数据并将其写入其中。借助这两个新类,您可以设计第一个步骤在队列中准备数据,并设计第二个步骤从同一队列消费数据。这样,两个步骤可以并发运行,以非阻塞、事件驱动的方式高效处理数据。
JPA 项读取器中的查询提示支持
直到 5.1 版本之前,JPA 游标和分页项读取器不支持查询提示(如获取大小、超时等)。 用户需要提供自定义查询提供程序才能指定自定义提示。
在此版本中,JPA 读取器及其各自的构建器已更新,可在定义要使用的 JPA 查询时接受查询提示。
JDBC 项读取器中的数据类支持
此版本在 JDBC 游标和分页项读取器的构建器中引入了一种新方法,允许用户在项类型为数据类(Java 记录或 Kotlin 数据类)时指定DataClassRowMapper。
名为 dataRowMapper(TargetType.class) 的新方法与 beanRowMapper(TargetType.class) 类似,旨在使行映射器在常规类(Java Bean)和数据类(Java Record)之间的配置保持一致。
RecursiveCollectionLineAggregator 中可配置的行分隔符
到目前为止,RecursiveCollectionLineAggregator 中的行分隔符属性被设置为系统的行分隔符值。
虽然可以通过系统属性更改该值,但这种配置风格与批处理构件的其他属性不一致。
此版本在 RecursiveCollectionLineAggregator 中引入了一个新的 setter,允许用户配置自定义的行分隔符值,而无需使用系统属性。
工作注册改进
在 5.1 版本中,批处理基础设施 Bean 的默认配置已更新,通过在应用上下文中定义一个 JobRegistryBeanPostProcessor Bean 来自动填充作业注册表。由于 Spring 框架最近的一次变更修改了 BeanPostProcessorChecker 中的日志级别,导致典型的 Spring Batch 应用中记录了许多与 JobRegistryBeanPostProcessor 相关的警告。这些警告是因为 JobRegistryBeanPostProcessor 依赖于一个 JobRegistry Bean,而这种做法并不推荐,可能会引发 Bean 生命周期问题。
这些问题在此版本中已通过更改填充 JobRegistry 的机制得到解决,从使用 BeanPostProcessor 改为使用 SmartInitializingSingleton。JobRegistryBeanPostProcessor 现已弃用,推荐使用新添加的 JobRegistrySmartInitializingSingleton。