抢先一步
VMware 提供培训和认证,助您快速提升技能。
了解更多它终于来了!Spring Batch 5.0 现已从 Maven Central 正式发布。Spring Batch 5 是两年工作的成果,包括 50 多位贡献者做出的数十项改进、功能和错误修复!我谨代表团队感谢所有参与此重大发布的贡献者!
这篇博文将介绍此框架新一代的主要亮点。您可以在发行说明中找到所有更改的详细信息,并在迁移指南中找到升级说明。
Spring Batch 遵循 Spring Framework 的 Java 版本和第三方依赖项基线。在 Spring Batch 5 中,Spring Framework 版本升级到 Spring Framework 6,这需要 Java 17。因此,Spring Batch 的 Java 版本要求也提高到 Java 17。
为了继续与 Spring Batch 使用的支持版本的第三方库集成,Spring Batch 5 正在全面更新依赖项到以下版本:
此版本还标志着迁移到:
为使用 GraalVM native-image 编译器将 Spring Batch 应用程序编译为原生可执行文件提供支持的工作始于 v4.2,并在 v4.3 中作为实验性功能发布。
在此版本中,通过提供必要的提前 (Ahead-Of-Time) 处理和运行时提示以使用 GraalVM 本地编译 Spring Batch 应用程序,原生支持得到了显着改进。
在此博文中,我们想与您分享我们在该领域进行的一些基准测试。以下基准测试基于batch示例(来自Spring Native示例项目)。这些基准测试显示了使用常规 JVM 和作为原生可执行文件执行的相同批处理应用程序的启动时间和总执行时间的比较。
此处显示的值是使用以下软件和硬件设置对样本执行 10 次的平均值:
如这些基准测试所示,原生 Spring Batch 应用程序的启动速度提高了两倍,运行时速度提高了近十倍!这对于云原生批处理工作负载来说确实是一个改变游戏规则的功能!
随着升级到 Micrometer 1.10,您现在除了批处理指标之外还可以获得批处理跟踪。Spring Batch 将为每个作业创建一个跨度,并为作业中的每个步骤创建一个跨度。此跟踪元数据可以在仪表板上收集和查看,例如Zipkin。
此外,此版本引入了新的指标:
job.launch.count
:这是一个Counter
,报告通过JobLauncher
启动了多少个作业。这对于批处理作业在持续运行的 JVM 中调度和执行的环境非常方便。step.active
:此LongTaskTimer
类型的指标报告特定作业中当前活动的(即正在运行的)步骤。此指标在作业有多个步骤并且想要知道处理当前发生在哪个步骤的情况下很有用。除了 Spring Batch 已经在执行上下文中关于运行时信息(如步骤类型、重启标志等)持久化存储的内容之外,此版本还在执行上下文中添加了一个重要的细节,即用于序列化上下文的 Spring Batch 版本。
虽然这看起来是一个细节,但在调试与执行上下文序列化和反序列化相关的升级问题时,它具有巨大的附加价值。
在此版本中,DefaultExecutionContextSerializer
已更新为将上下文序列化/反序列化为/从 Base64。
此外,@EnableBatchProcessing
或DefaultBatchConfiguration
配置的默认ExecutionContextSerializer
已从JacksonExecutionContextStringSerializer
更改为DefaultExecutionContextSerializer
。现在 Jackson 依赖项是可选的。为了使用JacksonExecutionContextStringSerializer
,应将jackson-core
添加到类路径中。
在此版本中重新审视了SystemCommandTasklet
,并进行了如下更改:
引入了一个名为CommandRunner
的新策略接口,以便将命令执行与任务执行分离。默认实现是JvmCommandRunner
,它使用java.lang.Runtime#exec
API 运行系统命令。可以实现此接口以使用任何其他 API 运行系统命令。
现在,运行命令的方法接受一个表示命令及其参数的String
数组。无需再对命令进行标记化或进行任何预处理。此更改使 API 更直观,并且更不容易出错。
在 4.x 版本之前,Spring Batch 仅支持 4 种类型作为作业参数,分别是 long
、double
、String
和 Date
。虽然这简化了框架侧的作业参数处理,但也限制了用户的使用。例如,如果用户想使用 boolean
或自定义类型作为作业参数怎么办?这需要将参数转换为 Spring Batch 支持的类型之一,这很快就会给用户带来不便。
在本版本中,我们添加了对使用任何类型作为作业参数的支持。此改进背后的主要更改如下所示:
---public class JobParameter implements Serializable {
+++public class JobParameter<T> implements Serializable {
--- private Object parameter;
+++ private T value;
--- private ParameterType parameterType;
+++ private Class<T> type;
}
此更改会影响作业参数在数据库中的持久化方式。请查看 迁移指南了解数据库模式的更改。参数类型的全限定名称现在作为 String
持久化,参数值也一样。字符串字面量使用标准的 Spring 转换服务转换为参数类型。标准转换服务可以添加任何所需的转换器,用于将用户特定的类型转换为字符串字面量或从字符串字面量转换回来。
v4 版本中作业参数的默认表示法如下所示:
[+|-]parameterName(parameterType)=parameterValue
其中 parameterType
是 [string,long,double,date]
之一。虽然这种表示法简洁,但它也存在一些局限性,因为它与环境变量不兼容,并且对 Spring Boot 不友好。
在 v5 版本中,我们更改了默认表示法,如下所示:
parameterName=parameterValue,parameterType,identificationFlag
其中 parameterType
是参数类型的全限定名称。例如,以下键值对:
schedule.date=2022-12-12,java.time.LocalDate
将转换为类型为 java.time.LocalDate
、值为 2022-12-12
的识别作业参数。请注意,识别标志是可选的,默认为 true
。这种新的默认表示法适用于大多数用例,但在值包含逗号等字符时可能不方便。为此,我们引入了一种新的“扩展”表示法,它受到 Spring Boot 的 Json 应用属性 的启发,并指定如下:
parameterName='{"value": "parameterValue", "type":"parameterType", "identifying": "booleanValue"}'
其中 parameterType
是参数类型的全限定名称。Spring Batch 提供了 JsonJobParametersConverter
来支持此表示法。当然,可以通过实现策略接口 JobParametersConverter
并将自定义实现注册到作业存储库和作业资源管理器中来支持任何其他表示法。
我们相信 Spring Batch 中这两项关于作业参数处理的主要更改更加方便、灵活,并且更不容易出错。
@EnableBatchProcessing
注解的新属性在本版本中,@EnableBatchProcessing
注解引入了新的属性来指定哪些组件和参数应该用于配置 Batch 基础设施 Bean。例如,您现在可以指定 Spring Batch 应该在作业存储库中配置哪些数据源和事务管理器。以下代码片段展示了这种新的配置方式:
@Configuration
@EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
public class MyJobConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
}
在此示例中,batchDataSource
和 batchTransactionManager
指的是应用上下文中的 Bean,它们用于配置作业存储库和作业资源管理器。您不再需要定义自定义的 BatchConfiguer
,该类已在本版本中移除。例如,在 Spring Batch v4 中,可以通过提供自定义的 BatchConfigurer
来提供自定义的执行上下文序列化器,如下所示:
@Configuration
@EnableBatchProcessing
public class MyJobConfigWithCustomSerializer {
@Bean
public BatchConfigurer batchConfigurer() {
return new DefaultBatchConfigurer() {
@Override
public JobRepository getJobRepository() {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setSerializer(createCustomSerializer());
// set other properties on the factory bean
try {
factory.afterPropertiesSet();
return factory.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public JobExplorer getJobExplorer() {
JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
factoryBean.setSerializer(createCustomSerializer());
// set other properties on the factory bean
try {
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private ExecutionContextSerializer createCustomSerializer() {
Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
// customize serializer
return serializer;
}
};
}
}
在 Spring Batch v5 中,您可以按如下方式提供自定义序列化器:
@Configuration
@EnableBatchProcessing(executionContextSerializerRef = "myCustomSerializer")
public class MyJobConfigWithCustomSerializer {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
@Bean
public ExecutionContextSerializer myCustomSerializer() {
Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
// customize serializer
return serializer;
}
}
我们相信这种新的配置 Spring Batch 的方式更加直观、简单,并且更不容易出错。
在本版本中,您可以使用一个名为 DefaultBatchConfiguration
的新配置类,作为使用 @EnableBatchProcessing
配置基础设施 Bean 的替代方案。此类提供具有默认配置的基础设施 Bean,您可以根据需要对其进行自定义。以下代码片段展示了此类的典型用法:
@Configuration
class MyJobConfiguration extends DefaultBatchConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
}
在此示例中,Job
Bean 定义中注入的 JobRepository
Bean 在 DefaultBatchConfiguration
类中定义。您可以通过覆盖相应的 getter 来指定自定义参数。例如,以下示例展示了如何覆盖作业存储库和作业资源管理器中使用的默认字符编码:
@Configuration
class MyJobConfiguration extends DefaultBatchConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("job", jobRepository)
// define job flow as needed
.build();
}
@Override
protected Charset getCharset() {
return StandardCharsets.ISO_8859_1;
}
}
此版本在通过 JobExplorerFactoryBean
创建的 JobExplorer
中引入了事务支持。您现在可以指定哪个事务管理器用于在查询批处理元数据时驱动只读事务。此外,您现在还可以自定义事务属性。通过一个名为 JobOperatorFactoryBean
的新工厂 Bean,同样的事务支持也添加到 JobOperator
中。
@EnableBatchProcessing
自动注册作业操作器从 4.x 版本开始,@EnableBatchProcessing
注解提供了启动 Spring Batch 作业所需的所有基本基础设施 Bean。但是,它没有注册作业操作器 Bean,它是停止、重新启动和放弃作业执行的主要入口点。
虽然这些实用程序不像启动作业那样经常使用,但在应用上下文中自动添加作业操作器可以避免最终用户手动配置此 Bean,从而非常有用。
在 4.3 版本之前,JobLauncherTestUtils
用于自动装配正在测试的作业,以便于测试设置。但是,如果测试上下文中定义了多个作业怎么办?如果根本没有定义 Job
Bean 怎么办?因此,虽然这种自动装配在大多数情况下都很方便,但事实证明它在上述情况下会导致一些问题。在本版本中,根据社区的反馈,我们决定移除 JobLauncherTestUtils
中任何作业的自动装配。
类似地,JobRepositoryTestUtils
用于从应用上下文中自动装配 DataSource
。同样,如果测试上下文中没有定义数据源或定义了多个数据源怎么办?在此版本中,JobRepositoryTestUtils
已更新为针对 JobRepository
接口工作,无需处理存储库的任何实现细节(例如数据源)。
如果您在测试上下文中手动定义这些实用程序 Bean 或通过 @SpringBatchTest
导入它们,则当测试上下文中定义了多个这些类型的 Bean 时,您将手动设置正在测试的作业或测试数据源。
在本版本中,Spring Batch 的整个测试套件已迁移到 JUnit 5。虽然这不会直接影响最终用户,但它可以帮助 Batch 团队以及社区贡献者使用下一代 JUnit 来编写更好的测试。
在 v4.3 中最初引入了对 Java 记录作为分块导向步骤中的项的支持,但由于 v4 以 Java 8 作为基线,因此该支持有限。在 Java 8 中,记录甚至还没有预览版。最初的支持是基于反射技巧来创建 Java 记录并使用数据填充它们,而无需访问在 Java 16 中最终确定的 java.lang.Record
API。
现在 v5 以 Java 17 作为基线,我们通过在框架的不同部分利用 java.lang.Record
API 改进了 Spring Batch 中的记录支持。例如,FlatFileItemReaderBuilder
现在能够检测项目类型是记录还是普通类,并相应地配置相应的 FieldSetMapper
实现(记录使用 RecordFieldSetMapper
,普通类使用 BeanWrapperFieldSetMapper
)。此处的目标是使所需 FieldSetMapper
类型的配置对用户透明。相同的特性也已在 FlatFileItemWriterBuilder
中实现,以便根据项目类型配置 RecordFieldExtractor
或 BeanWrapperFieldExtractor
。
多年来,在框架的不同领域报告了许多与字符编码相关的问题,例如基于文件的项目读取器和写入器之间不一致的默认编码、处理执行上下文中的多字节字符时的序列化/反序列化问题等。
本着与JEP 400相同的精神,并遵循UTF-8 宣言,我们在框架的所有领域都将默认编码更改为 UTF-8
,并在适当的地方使此默认值可配置。
我们借此主要版本的机会,使用 Java 8 及更高版本的功能来改进代码库,例如
@FunctionalInterface
(参见问题 4107)此功能已多次被请求,并最终在此版本中发布。现在可以使用新添加的 Maven BOM 以一致的版本号导入 Spring Batch 模块。
在 v4.3 之前,Spring Batch 通过将 MariaDB 视为 MySQL 来提供对它的支持。在此版本中,MariaDB 现在被视为一个独立的数据库产品,具有自己的 DDL 脚本和 DataFieldMaxValueIncrementer
。
SAP Hana 现在在 Spring Batch 中正式支持作为作业存储库。
在此版本中,文档已更新为使用Spring Asciidoctor 后端。此后端确保产品组合中的所有项目都遵循相同的文档风格。为了与其他项目保持一致,Spring Batch 的参考文档已在此版本中更新为使用此后端。您可以此处查看参考文档的新版本。
在此主要版本中,先前版本中弃用的所有 API 都已移除。此外,一些 API 在 v5.0 中已弃用,并计划在 v5.2 中移除。最后,出于实际原因,一些 API 已移动或移除,而无需弃用。有关所有弃用 API 的列表,请参阅迁移指南。
SQLFire 已于 2014 年 11 月 1 日宣布停止使用。v4.3 版本中已弃用 SQLFire 作为作业存储库的支持,并在 v5.0 版本中移除。
根据停止支持 Spring Data for Apache Geode 的决定,已移除 Spring Batch 中对 Apache Geode 的支持。
代码已作为社区驱动的努力移至spring-batch-extensions存储库。
由于采用率不足,在此版本中已停止使用 JSR-352 的实现。
一些错误无法在不引入重大更改的情况下修复。我们借此主要版本的机会修复此类错误。请参阅发行说明,了解在此版本中修复的 40 多个错误的完整列表!
我要感谢所有参与此重大版本的贡献者!如果没有整个 Spring 社区,特别是 Spring Batch 社区的帮助,这个版本是不可能实现的。我们很乐意听取您对这个主要版本的反馈,以及它如何改进您的批处理基础设施。请在Github、Twitter 和StackOverflow上提交您的反馈。
由于我们刚刚发布了下一代 Spring Batch 的第一个版本,我们仍然有很多想法和功能正在开发中或计划在下一个版本中开发,例如
我们将在不久的将来与您分享我们的完整路线图,并向您展示如何参与这些新功能的早期开发和测试阶段。敬请期待!