JSR-352 支持
JSR-352 支持
从 Spring Batch 3.0 开始,对 JSR-352 的支持已经完全实现。本节不能替代 规范本身,而是旨在解释 JSR-352 特定概念如何应用于 Spring Batch。 有关 JSR-352 的更多信息,请访问 JCP 在这里:https://jcp.org/en/jsr/detail?id=352
关于 Spring Batch 和 JSR-352 的一般说明
Spring Batch 和 JSR-352 在结构上是相同的。他们都有由台阶组成的工作。他们
两者都有读取器、处理器、写入器和侦听器。然而,它们的互动却略有不同。
例如,org.springframework.batch.core.SkipListener#onSkipInWrite(S item, Throwable t)
在 Spring Batch 中接收两个参数:被跳过的项目和导致
跳。相同方法的 JSR-352 版本
(javax.batch.api.chunk.listener.SkipWriteListener#onSkipWriteItem(List<Object> items, Exception ex)
)
还接收两个参数。然而,第一个是List
所有项目的
在当前块中,第二个是Exception
这导致了跳过。
由于这些差异,请务必注意,在
Spring Batch:传统的 Spring Batch 作业或基于 JSR-352 的作业。而使用 Spring Batch
工件(读取器、写入器等)将在使用 JSR-352 的 JSL 配置的作业中工作,并使用JsrJobOperator
,它们将按照 JSR-352 的规则进行作。它也是
重要的是要注意,针对 JSR-352 接口开发的批处理工件将不起作用
在传统的 Spring Batch 作业中。
设置
应用程序上下文
Spring Batch 中所有基于 JSR-352 的作业都由两个应用程序上下文组成。父上下文,即
包含与 Spring Batch 的基础设施相关的 bean,例如JobRepository
,PlatformTransactionManager
等,以及由配置组成的子上下文
要运行的作业。父上下文通过jsrBaseContext.xml
提供
由框架。可以通过设置JSR-352-BASE-CONTEXT
系统
财产。
JSR-352 处理器不会处理基本上下文,用于属性注入之类的事情,因此 无需配置其他处理的组件。 |
启动基于 JSR-352 的作业
JSR-352 需要一个非常简单的路径来执行批处理作业。以下代码是 执行第一个批处理作业:
JobOperator operator = BatchRuntime.getJobOperator();
jobOperator.start("myJob", new Properties());
虽然这对开发人员来说很方便,但细节决定成败。Spring Batch 引导一些
开发人员可能想要覆盖的幕后基础设施。下面是引导的
第一次BatchRuntime.getJobOperator()
称为:
豆名 |
默认配置 |
笔记 |
数据源 |
Apache DBCP BasicDataSource 与配置的值。 |
默认情况下,HSQLDB 是引导的。 |
|
|
引用上面定义的 dataSource bean。 |
数据源初始值设定项 |
这配置为执行通过 |
|
job存储库 |
基于 JDBC |
这 |
jobLauncher |
|
用于启动作业。 |
batchJob运算符 |
|
这 |
作业浏览器 |
|
用于解决 |
jobParameters转换器 |
|
JSR-352 的具体实现 |
job注册表 |
|
由 |
占位符属性 |
|
加载属性文件 |
对于执行基于 JSR-352 的作业,上述 bean 都不是可选的。所有 都可以覆盖为 根据需要提供定制功能。 |
依赖注入
JSR-352 在很大程度上基于 Spring Batch 编程模型。因此,虽然没有明确要求 正式的依赖注入实现,隐含某种 DI。Spring Batch 支持这三个 JSR-352 定义的批量工件的加载方法:
-
实现特定加载器:Spring Batch 基于 Spring 构建,因此支持 JSR-352 批处理作业中的 Spring 依赖注入。
-
存档加载器:JSR-352 定义了现有的
batch.xml
提供映射的文件 在逻辑名称和类名之间。此文件必须在/META-INF/
目录(如果使用)。 -
线程上下文类加载器:JSR-352 允许配置指定批处理工件 通过内联提供完全限定的类名来实现。Spring Batch 在 JSR-352 配置的作业中也支持此功能。
要在基于 JSR-352 的批处理作业中使用 Spring 依赖注入,包括
使用 Spring 应用程序上下文作为 bean 配置批处理工件。曾经的豆子
,作业可以引用它们,就像引用batch.xml
文件。
以下示例显示了如何在基于 JSR-352 的 XML 中的批处理作业:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://xmlns.jcp.org/xml/ns/javaee
https://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd">
<!-- javax.batch.api.Batchlet implementation -->
<bean id="fooBatchlet" class="io.spring.FooBatchlet">
<property name="prop" value="bar"/>
</bean>
<!-- Job is defined using the JSL schema provided in JSR-352 -->
<job id="fooJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="step1">
<batchlet ref="fooBatchlet"/>
</step>
</job>
</beans>
以下示例显示了如何在基于 JSR-352 的 Java 中的批处理作业:
@Configuration
public class BatchConfiguration {
@Bean
public Batchlet fooBatchlet() {
FooBatchlet batchlet = new FooBatchlet();
batchlet.setProp("bar");
return batchlet;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<job id="fooJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="step1" >
<batchlet ref="fooBatchlet" />
</step>
</job>
Spring 上下文(导入等)的汇编与 JSR-352 作业一起工作,就像它与任何其他作业一样 基于弹簧的应用程序。与基于 JSR-352 的作业的唯一区别是 context definition 将是 /META-INF/batch-jobs/ 中找到的作业定义。
要使用线程上下文类加载器方法,您需要做的就是提供完全限定的类
name 作为引用。请务必注意,当使用此方法或batch.xml
方法,类
referenced 需要一个 no argument 构造函数,该构造函数将用于创建 bean。
<?xml version="1.0" encoding="UTF-8"?>
<job id="fooJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="step1" >
<batchlet ref="io.spring.FooBatchlet" />
</step>
</job>
批处理属性
物业支持
JSR-352 允许通过以下方式在作业、步骤和批处理工件级别定义属性 JSL 中的配置。批处理属性按以下方式在每个级别配置:
<properties>
<property name="propertyName1" value="propertyValue1"/>
<property name="propertyName2" value="propertyValue2"/>
</properties>
Properties
可以在任何批处理工件上配置。
@BatchProperty注释
Properties
通过使用@BatchProperty
和@Inject
注释(两个注释
规范要求)。根据 JSR-352 的定义,属性字段必须是字符串类型。任何类型
转换由实现开发人员执行。
一javax.batch.api.chunk.ItemReader
artifact 可以配置
properties 块,例如上面描述的块,并按以下方式访问:
public class MyItemReader extends AbstractItemReader {
@Inject
@BatchProperty
private String propertyName1;
...
}
字段“propertyName1”的值将为“propertyValue1”
属性替换
属性替换是通过运算符和简单的条件表达式提供的。一般
用法是#{operator['key']}
.
支持的运算符:
-
jobParameters
:访问启动/重新启动作业时使用的作业参数值。 -
jobProperties
:访问在 JSL 的作业级别配置的属性。 -
systemProperties
:访问命名系统属性。 -
partitionPlan
:从分区步骤的分区计划中访问命名属性。
#{jobParameters['unresolving.prop']}?:#{systemProperties['file.separator']}
赋值的左侧是期望值,右侧是 默认值。在前面的 例如,结果将解析为系统属性 file.separator 的值,作为 #{jobParameters['unresolving.prop']} 假定为不可解析。如果两者都不是 表达式,将返回一个空的 String。可以有多种条件 used,用 ';' 分隔。
处理模型
JSR-352 提供了与 Spring Batch 相同的两个基本处理模型:
-
基于项目的处理 - 使用
javax.batch.api.chunk.ItemReader
,可选的javax.batch.api.chunk.ItemProcessor
和javax.batch.api.chunk.ItemWriter
. -
基于任务的处理 - 使用
javax.batch.api.Batchlet
实现。此处理模型与org.springframework.batch.core.step.tasklet.Tasklet
基于处理 目前可用。
基于项目的处理
在此上下文中,基于项目的处理是由ItemReader
.要以这种方式配置步骤,请指定item-count
(默认为 10),并可选择配置checkpoint-policy
作为项目(这是默认值)。
...
<step id="step1">
<chunk checkpoint-policy="item" item-count="3">
<reader ref="fooReader"/>
<processor ref="fooProcessor"/>
<writer ref="fooWriter"/>
</chunk>
</step>
...
如果选择基于项的检查点,则附加属性time-limit
被支持。
这设置了必须处理指定项目数量的时间限制。如果
达到超时时,该块将完成,无论读取了多少项
那么无论item-count
配置为。
自定义检查点
JSR-352 将步骤内提交间隔周围的进程称为“检查点”。基于项目的检查点是上面提到的一种方法。但是,这并不健壮在许多情况下足够。因此,该规范允许通过实现javax.batch.api.chunk.CheckpointAlgorithm
接口。此功能在功能上与 Spring Batch 的自定义补全相同
政策。要使用CheckpointAlgorithm
,使用
习惯checkpoint-policy
如下图所示,其中fooCheckpointer
指的是一个
实现CheckpointAlgorithm
.
...
<step id="step1">
<chunk checkpoint-policy="custom">
<checkpoint-algorithm ref="fooCheckpointer"/>
<reader ref="fooReader"/>
<processor ref="fooProcessor"/>
<writer ref="fooWriter"/>
</chunk>
</step>
...
运行作业
执行基于 JSR-352 的作业的入口是通过javax.batch.operations.JobOperator
.Spring Batch 提供了自己的实现
此接口 (org.springframework.batch.core.jsr.launch.JsrJobOperator
).这
实现是通过javax.batch.runtime.BatchRuntime
.启动
基于 JSR-352 的批处理作业实现如下:
JobOperator jobOperator = BatchRuntime.getJobOperator();
long jobExecutionId = jobOperator.start("fooJob", new Properties());
上面的代码执行以下作:
-
引导一个基础
ApplicationContext
:为了提供批处理功能,请 框架需要一些引导的基础设施。每个 JVM 都会发生一次。这 引导的组件类似于@EnableBatchProcessing
.具体细节可以在 javadoc 中找到JsrJobOperator
. -
加载一个
ApplicationContext
对于请求的作业:在示例中 上面,框架在 /META-INF/batch-jobs 中查找名为 fooJob.xml 的文件并加载一个 context,它是前面提到的共享上下文的子项。 -
启动作业:上下文中定义的作业将异步执行。 这
JobExecution’s
身份证件将被退回。
所有基于 JSR-352 的批处理作业都是异步执行的。 |
什么时候JobOperator#start
使用SimpleJobOperator
,Spring Batch 确定是否
调用是对以前执行的运行的初始运行或重试。使用 JSR-352
基于JobOperator#start(String jobXMLName, Properties jobParameters)
、框架
将始终创建一个新的 JobInstance(JSR-352 作业参数是非标识性的)。为了
重新启动作业,调用JobOperator#restart(long executionId, Properties restartParameters)
是必需的。
上下文
JSR-352 定义了两个上下文对象,用于与作业的元数据或步骤进行交互
在批处理工件中:javax.batch.runtime.context.JobContext
和javax.batch.runtime.context.StepContext
.这两者都可以在任何步骤中使用
关卡工件(Batchlet
,ItemReader
等)替换为JobContext
也可用于作业级别工件
(JobListener
例如)。
要获取对JobContext
或StepContext
在当前范围内,只需使用@Inject
注解:
@Inject
JobContext jobContext;
JSR-352 上下文的@Autowire
不支持使用 Spring 的@Autowire注入这些上下文。 |
在 Spring Batch 中,JobContext
和StepContext
将他们的
相应的执行对象(JobExecution
和StepExecution
分别)。通过StepContext#setPersistentUserData(Serializable data)
存储在
弹簧批次StepExecution#executionContext
.
步骤流程
在基于 JSR-352 的作业中,步骤流的工作方式与在 Spring Batch 中类似。但是,有一些细微的区别:
-
决策是步骤- 在常规的 Spring Batch 作业中,决策是一种状态,它没有有一个独立的
StepExecution
或任何权利和作为完整步骤所伴随的责任。然而,对于 JSR-352,决策是一个步骤,就像其他步骤一样,并且其行为与任何其他步骤(事务性,它会得到一个StepExecution
等)。这意味着它们被视为与重新启动时的任何其他步骤相同。 -
next
属性和步骤转换 - 在常规作业中,这些是允许在同一步骤中一起出现。JSR-352 允许它们同时用于同一步骤,下一个属性在评估中优先。 -
过渡元素排序 - 在标准 Spring Batch 作业中,过渡元素是 从最具体到最不具体排序,并按该顺序进行评估。JSR-352 作业 按照 XML 中指定的顺序评估过渡元素。
扩展 JSR-352 批处理作业
传统的 Spring Batch 作业有四种扩展方式(最后两种能够跨 多个 JVM):
-
拆分 - 并行运行多个步骤。
-
多线程 - 通过多个线程执行单个步骤。
-
分区 - 将数据划分为并行处理(管理器/辅助角色)。
-
远程分块 - 远程执行处理器逻辑片段。
JSR-352 提供了两个用于扩展批处理作业的选项。这两个选项都只支持一个 JVM:
-
拆分 - 与弹簧批处理相同
-
分区 - 在概念上与 Spring Batch 相同,但实现略有不同。
分区
从概念上讲,JSR-352 中的分区与 Spring Batch 中的分区相同。提供元数据 给每个工作人员以确定要处理的输入,工作人员向经理报告 完成后的结果。但是,有一些重要的区别:
-
分区
Batchlet
- 这将运行 配置Batchlet
在多个线程上。每个实例将有 它自己的属性集由 JSL 或PartitionPlan
-
PartitionPlan
- 使用 Spring Batch 的分区,一个ExecutionContext
为每个分区提供。使用 JSR-352 时,一个 单javax.batch.api.partition.PartitionPlan
提供了一个 数组Properties
为每个分区提供元数据。 -
PartitionMapper
- JSR-352 提供了两种生成分区的方法 元数据。一种是通过 JSL(分区属性)。第二种是通过实现 的javax.batch.api.partition.PartitionMapper
接口。 在功能上,此接口类似于org.springframework.batch.core.partition.support.Partitioner
Spring Batch 提供的接口,因为它提供了一种以编程方式生成 元数据进行分区。 -
StepExecutions
- 在 Spring Batch 中,分区步骤以 经理/工人。在 JSR-352 中,发生相同的配置。但是,工作器步骤会 没有得到官方的StepExecutions
.因此,调用JsrJobOperator#getStepExecutions(long jobExecutionId)
只会 返回StepExecution
对于经理来说。
孩子 |
-
补偿逻辑 - 由于 Spring Batch 实现了 使用步骤进行分区,
StepExecutionListeners
可用于 如果出现问题,则处理补偿逻辑。然而,由于工人 JSR-352 提供了其他组件的集合,以便在以下情况下提供补偿逻辑 错误,并动态设置退出状态。这些组件包括以下内容:
工件接口 |
描述 |
|
为辅助角色步骤提供一种将信息发送回 经理。每个工作线程有一个实例。 |
|
接收 |
|
提供为分区的 步。 |