配置和运行作业
配置和运行作业
在 domain 部分 ,总体 讨论了架构设计,使用下图作为 指导:
虽然该对象可能看起来很简单
容器中,您必须了解许多配置选项。
此外,您必须考虑许多关于
如何运行 A 及其元数据
在该运行期间存储。本章介绍各种配置
选项和运行时问题。Job
Job
Job
配置 Job
Job
接口有多种实现。然而
构建器抽象出配置中的差异。
以下示例创建一个 :footballJob
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.start(playerLoad())
.next(gameLoad())
.next(playerSummarization())
.build();
}
A(通常还包括其中的任何一个)需要一个 .这
的配置通过 Java 配置
进行处理。Job
Step
JobRepository
JobRepository
前面的示例说明了由三个实例组成的 a。工作相关
构建器还可以包含有助于并行化 () 的其他元素,
声明式流控制 (),以及流定义 () 的外部化。Job
Step
Split
Decision
Flow
Job
接口有多种实现。但是,命名空间抽象出了配置中的差异。它有
只有三个必需的依赖项:名称、 和实例列表。
以下示例创建一个 :JobRepository
Step
footballJob
<job id="footballJob">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s2" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
</job>
此处的示例使用父 Bean 定义来创建步骤。
请参阅 步骤配置 部分,了解内联声明特定步骤详细信息时的更多选项。XML 命名空间
默认引用 ID 为 的存储库,该存储库
是合理的默认值。但是,您可以显式覆盖它:jobRepository
<job id="footballJob" job-repository="specialRepository">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s3" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
</job>
除了步骤之外,作业配置还可以包含其他有助于
并行化 ()、声明式流控制 () 和外部化
流定义 () 的<split>
<decision>
<flow/>
可重启性
执行批处理作业时的一个关键问题涉及
重新 启动。如果特定 已存在 a,则启动 a 被视为“重新启动”。理想情况下,所有作业都应该能够启动
从他们离开的地方开始,但在某些情况下这是不可能的。在这种情况下,完全由开发人员来确保创建新的 JobInstance
。但是,Spring Batch 确实提供了一些帮助。如果 a 不应该是
重新启动,但应始终作为 new 的一部分运行,您可以设置
restartable 属性设置为 。Job
Job
JobExecution
JobInstance
Job
JobInstance
false
以下示例演示如何在 XML 中将字段设置为 :restartable
false
<job id="footballJob" restartable="false">
...
</job>
以下示例演示如何在 Java 中将字段设置为 :restartable
false
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.preventRestart()
...
.build();
}
换句话说,设置为 to 意味着 “this does not support being started again”。重新启动 不是
restartable 会导致
被扔掉。
以下 Junit 代码会导致引发异常:restartable
false
Job
Job
JobRestartException
Job job = new SimpleJob();
job.setRestartable(false);
JobParameters jobParameters = new JobParameters();
JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
jobRepository.saveOrUpdate(firstExecution);
try {
jobRepository.createJobExecution(job, jobParameters);
fail();
}
catch (JobRestartException e) {
// expected
}
第一次尝试为 不可重启
job 不会引起任何问题。然而,第二个
attempt 会引发 .JobExecution
JobRestartException
拦截任务执行
在执行 的过程中,通知各种 可能会很有用
事件,以便可以运行自定义代码。 通过在适当的时间调用 A 来允许此操作:Job
SimpleJob
JobListener
public interface JobExecutionListener {
void beforeJob(JobExecution jobExecution);
void afterJob(JobExecution jobExecution);
}
您可以通过在作业上设置侦听器来添加到 。JobListeners
SimpleJob
以下示例演示如何将侦听器元素添加到 XML 作业定义中:
<job id="footballJob">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s2" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
<listeners>
<listener ref="sampleListener"/>
</listeners>
</job>
以下示例说明如何将侦听器方法添加到 Java 作业定义中:
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.listener(sampleListener())
...
.build();
}
请注意,无论成功还是
失败的 .如果需要确定成功或失败,可以获取该信息
从 :afterJob
Job
JobExecution
public void afterJob(JobExecution jobExecution){
if (jobExecution.getStatus() == BatchStatus.COMPLETED ) {
//job success
}
else if (jobExecution.getStatus() == BatchStatus.FAILED) {
//job failure
}
}
与此接口对应的注解是:
-
@BeforeJob
-
@AfterJob
从父作业继承
如果一组 Job 具有相似但不相似的
相同的配置,定义一个 “parent” 可能会有所帮助,具体实例可以从中继承属性。与 class 相似
继承,则“子”结合了
它的元素和属性与父级的 Elements 和 Attributes 一起使用。Job
Job
Job
在下面的示例中,是一个抽象定义,它只定义了
听众。() 是具体的
继承侦听器列表并合并的定义
it 替换为自己的侦听器列表,以生成具有两个侦听器和一个 () 的 a。baseJob
Job
Job
job1
baseJob
Job
Step
step1
<job id="baseJob" abstract="true">
<listeners>
<listener ref="listenerOne"/>
<listeners>
</job>
<job id="job1" parent="baseJob">
<step id="step1" parent="standaloneStep"/>
<listeners merge="true">
<listener ref="listenerTwo"/>
<listeners>
</job>
请参阅 从父步骤继承 有关更多详细信息的部分。
JobParametersValidator (作业参数验证器)
在 XML 命名空间中声明的作业或使用 的任何子类可以选择为
运行。例如,当您需要断言作业
启动其所有必需参数。有一个 可用于约束组合
简单的强制和可选参数。对于更复杂的
constraints,您可以自行实现接口。AbstractJob
DefaultJobParametersValidator
验证器的配置是通过 XML 命名空间通过子 元素,如下例所示:
<job id="job1" parent="baseJob3">
<step id="step1" parent="standaloneStep"/>
<validator ref="parametersValidator"/>
</job>
您可以将验证器指定为引用(如前所述)或嵌套 Bean
定义。beans
验证器的配置通过 Java 构建器支持:
@Bean
public Job job1(JobRepository jobRepository) {
return new JobBuilder("job1", jobRepository)
.validator(parametersValidator())
...
.build();
}
Java 配置
Spring 3 带来了使用 Java 而不是 XML 配置应用程序的能力。截至
Spring Batch 2.2.0 中,您可以使用相同的 Java 配置来配置批处理作业。
基于 Java 的配置有三个组件:注释和两个构建器。@EnableBatchProcessing
该注释的工作方式类似于
Spring 家族。在这种情况下,为
构建批处理作业。在此基本配置中,和 的实例是
created,此外还有许多 bean 可用于 autowired:@EnableBatchProcessing
@Enable*
@EnableBatchProcessing
StepScope
JobScope
-
JobRepository
:一个名为jobRepository
-
JobLauncher
:一个名为jobLauncher
-
JobRegistry
:一个名为jobRegistry
-
JobExplorer
:一个名为jobExplorer
-
JobOperator
:一个名为jobOperator
默认实现提供前面列表中提到的 bean,并要求 a 和 a 在上下文中作为 bean 提供。数据源和交易
manager 由 和 实例使用。默认情况下,将使用名为 的数据源 和 名为 的事务管理器。您可以使用
注释的属性。以下示例演示如何提供
自定义数据源和事务管理器:DataSource
PlatformTransactionManager
JobRepository
JobExplorer
dataSource
transactionManager
@EnableBatchProcessing
@Configuration
@EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
public class MyJobConfiguration {
@Bean
public DataSource batchDataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL)
.addScript("/org/springframework/batch/core/schema-hsqldb.sql")
.generateUniqueName(true).build();
}
@Bean
public JdbcTransactionManager batchTransactionManager(DataSource dataSource) {
return new JdbcTransactionManager(dataSource);
}
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
}
只有一个 configuration class 需要有 annotation。一次
你有一个用它注释的类,你有前面描述的所有配置。@EnableBatchProcessing |
从 v5.0 开始,配置基本 infrastrucutre bean 的另一种编程方式
通过类提供。此类提供相同的 bean
由 提供,并可用作配置批处理作业的基类。
以下代码片段是如何使用它的典型示例:DefaultBatchConfiguration
@EnableBatchProcessing
@Configuration
class MyJobConfiguration extends DefaultBatchConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("job", jobRepository)
// define job flow as needed
.build();
}
}
数据源和事务管理器将从应用程序上下文中解析 并在 Job repository 和 Job Explorer 上进行设置。您可以自定义配置 通过覆盖所需的 setter 来获取。以下示例 演示如何自定义字符编码,例如:
@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;
}
}
@EnableBatchProcessing 不应与 一起使用。您应该
要么使用通过 ,
或使用扩展的编程方式,但不能双向扩展
同一时间。DefaultBatchConfiguration @EnableBatchProcessing DefaultBatchConfiguration |
配置 JobRepository
使用 时,将为您提供 a。
本节介绍如何配置您自己的@EnableBatchProcessing
JobRepository
如前所述,JobRepository
用于各种持久化
Spring Batch 中的域对象,例如 和 。
许多主要框架功能(如 、 和 )都需要它。JobExecution
StepExecution
JobLauncher
Job
Step
batch 命名空间抽象出 implementations 及其协作者的许多实现细节。但是,仍然有一些
可用的配置选项,如下例所示:JobRepository
<job-repository id="jobRepository"
data-source="dataSource"
transaction-manager="transactionManager"
isolation-level-for-create="SERIALIZABLE"
table-prefix="BATCH_"
max-varchar-length="1000"/>
除 之外,前面列出的任何配置选项都不是必需的。如果他们是
未设置,则使用前面显示的默认值。
默认为 ,这是示例架构中长列的长度
脚本。id
max-varchar-length
2500
VARCHAR
除了 和 之外,前面列出的任何配置选项都不是必需的。
如果未设置,则前面显示的默认值
使用。这
max length 默认为 ,即
示例架构脚本中长列的长度dataSource
transactionManager
varchar
2500
VARCHAR
JobRepository 的事务配置
如果使用 namespace 或 provided ,则事务性建议为
围绕存储库自动创建。这是为了确保批处理元数据
包括失败后重新启动所需的状态将正确保留。
如果存储库方法不是
事务。指定 method 属性中的隔离级别
以确保在启动作业时,如果两个进程尝试启动
同一时间执行相同的作业,只有一个成功。该
方法是 ,这是相当激进的。 通常效果相同
井。 如果两个进程在此中不太可能发生冲突,则很好
道路。但是,由于对该方法的调用非常短,因此只要数据库平台支持它,就不太可能导致问题。但是,您
可以覆盖此设置。FactoryBean
create*
SERIALIZABLE
READ_COMMITTED
READ_UNCOMMITTED
create*
SERIALIZED
以下示例演示如何在 XML 中覆盖隔离级别:
<job-repository id="jobRepository"
isolation-level-for-create="REPEATABLE_READ" />
以下示例演示如何在 Java 中覆盖隔离级别:
@Configuration
@EnableBatchProcessing(isolationLevelForCreate = "ISOLATION_REPEATABLE_READ")
public class MyJobConfiguration {
// job definition
}
如果未使用命名空间,则还必须配置 使用 AOP 的存储库的事务行为。
以下示例显示如何配置存储库的事务行为 在 XML 中:
<aop:config>
<aop:advisor
pointcut="execution(* org.springframework.batch.core..*Repository+.*(..))"/>
<advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
您可以几乎按原样使用前面的 fragment,几乎不需要任何更改。还要记住
包含适当的名称空间声明,并确保 and(或整个 Spring)在 Classpath 上。spring-tx
spring-aop
以下示例显示如何配置存储库的事务行为 在 Java 中:
@Bean
public TransactionProxyFactoryBean baseProxy() {
TransactionProxyFactoryBean transactionProxyFactoryBean = new TransactionProxyFactoryBean();
Properties transactionAttributes = new Properties();
transactionAttributes.setProperty("*", "PROPAGATION_REQUIRED");
transactionProxyFactoryBean.setTransactionAttributes(transactionAttributes);
transactionProxyFactoryBean.setTarget(jobRepository());
transactionProxyFactoryBean.setTransactionManager(transactionManager());
return transactionProxyFactoryBean;
}
更改表前缀
的另一个可修改属性是元数据的表前缀
表。默认情况下,它们都以 . 和 是两个例子。但是,有一些潜在的原因需要修改它
前缀。如果需要在表名前面加上架构名称,或者如果有多个
的元数据表集,则表前缀需要
被更改。JobRepository
BATCH_
BATCH_JOB_EXECUTION
BATCH_STEP_EXECUTION
以下示例演示如何更改 XML 中的表前缀:
<job-repository id="jobRepository"
table-prefix="SYSTEM.TEST_" />
以下示例演示如何在 Java 中更改表前缀:
@Configuration
@EnableBatchProcessing(tablePrefix = "SYSTEM.TEST_")
public class MyJobConfiguration {
// job definition
}
鉴于上述更改,对元数据表的每个查询都以 为前缀。 称为 。SYSTEM.TEST_
BATCH_JOB_EXECUTION
SYSTEM.TEST_JOB_EXECUTION
只有表前缀是可配置的。table 和 column name 不是。 |
存储库中的非标准数据库类型
如果您使用的数据库平台不在受支持平台列表中,则
如果 SQL 变体足够接近,则可能能够使用支持的类型之一。待办事项
这样,您可以使用 RAW 而不是命名空间快捷方式和
使用它来将 Database type (数据库类型) 设置为最接近的匹配项。JobRepositoryFactoryBean
以下示例演示如何使用 设置数据库类型
到 XML 中最接近的匹配项:JobRepositoryFactoryBean
<bean id="jobRepository" class="org...JobRepositoryFactoryBean">
<property name="databaseType" value="db2"/>
<property name="dataSource" ref="dataSource"/>
</bean>
以下示例演示如何使用 设置数据库类型
到 Java 中最接近的匹配项:JobRepositoryFactoryBean
@Bean
public JobRepository jobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setDatabaseType("db2");
factory.setTransactionManager(transactionManager);
return factory.getObject();
}
如果未指定数据库类型,则尝试
从 中自动检测数据库类型。
平台之间的主要区别是
主要由递增主键的策略负责,因此
通常还需要覆盖 (通过使用标准的
来自 Spring Framework 的实现)。JobRepositoryFactoryBean
DataSource
incrementerFactory
如果这不起作用,或者您没有使用 RDBMS,则
唯一的选项可能是实现
on 上,并以正常的 Spring 方式手动连接一个。Dao
SimpleJobRepository
配置 JobLauncher
当您使用 时,将为您提供 a。
本节介绍如何配置您自己的@EnableBatchProcessing
JobRegistry
该接口最基本的实现是 .
它唯一需要的依赖项是 a (需要获取执行)。JobLauncher
TaskExecutorJobLauncher
JobRepository
以下示例显示了 XML 格式:TaskExecutorJobLauncher
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.TaskExecutorJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
以下示例显示了 Java 中的一个:TaskExecutorJobLauncher
...
@Bean
public JobLauncher jobLauncher() throws Exception {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
...
获取 JobExecution 后,它会传递给
execute 方法,最终将 返回给调用者,作为
下图显示了:Job
JobExecution
该序列简单明了,从计划程序启动时效果很好。然而
尝试从 HTTP 请求启动时出现问题。在这种情况下,启动
需要异步完成,以便立即返回到其
访客。这是因为让 HTTP 请求保持打开状态并不是一个好的做法
长时间运行的进程(如批处理作业)所需的时间。下图显示了
示例序列:TaskExecutorJobLauncher
您可以通过配置 来配置 以允许此方案。TaskExecutorJobLauncher
TaskExecutor
下面的 XML 示例将 a 配置为立即返回:TaskExecutorJobLauncher
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.TaskExecutorJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
</property>
</bean>
下面的 Java 示例将 a 配置为立即返回:TaskExecutorJobLauncher
@Bean
public JobLauncher jobLauncher() {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
jobLauncher.setJobRepository(jobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
你可以使用 spring 接口的任何实现来控制 Job 的异步方式
执行。TaskExecutor
运行 Job
启动批处理作业至少需要两件事:要启动的作业和 .两者都可以包含在同一个
context 或不同的上下文。例如,如果您从
命令行中,将为每个 .因此,每个
Job 有自己的 .但是,如果
您可以从 范围内的 Web 容器中运行,通常有一个(为异步作业配置
launching),多个请求调用以启动其作业。Job
JobLauncher
Job
JobLauncher
HttpRequest
JobLauncher
从命令行运行 Job
如果要从企业运行作业
scheduler 中,命令行是主界面。这是因为
大多数调度程序(Quartz 除外,除非使用 )直接与 os 一起工作
进程,主要由 shell 脚本启动。有很多方法
启动除 shell 脚本之外的 Java 进程,例如 Perl、Ruby 或
甚至构建工具,例如 Ant 或 Maven。但是,因为大多数人
熟悉 shell 脚本,本示例重点介绍它们。NativeJob
The CommandLineJobRunner
因为启动作业的脚本必须启动 Java
Virtual Machine 中,需要有一个类,其中包含一个
作为主要入口点。Spring Batch 提供了一个实现
,用于此目的:。注意
这只是引导应用程序的一种方式。有
启动 Java 进程的方法有很多种,这个类绝不应该是
被视为确定的。执行四项任务:main
CommandLineJobRunner
CommandLineJobRunner
-
加载相应的 .
ApplicationContext
-
将命令行参数解析为 .
JobParameters
-
根据参数找到合适的作业。
-
使用应用程序上下文中提供的 来启动作业。
JobLauncher
所有这些任务都只需传入参数即可完成。 下表描述了所需的参数:
|
XML 文件的位置,用于
创建一个 .此文件
应包含运行完整 . |
|
要运行的作业的名称。 |
必须传入这些参数,路径在前,名称在后。所有参数
在这些被认为是作业参数后,它们被转换为对象,
,并且必须采用 .JobParameters
name=value
以下示例显示了作为作业参数传递给 XML 中定义的作业的日期:
<bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay schedule.date=2007-05-05,java.time.LocalDate
以下示例显示了作为作业参数传递给 Java 中定义的作业的日期:
<bash$ java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay schedule.date=2007-05-05,java.time.LocalDate
默认情况下,它使用隐式转换
用于标识作业参数的键/值对。但是,您可以显式指定
哪些作业参数正在标识,哪些不是,分别通过给它们加上 或 后缀。 在以下示例中, is 是一个标识作业参数,while is not:
您可以通过使用自定义 . |
在大多数情况下,您需要使用 manifest 在 jar 中声明您的类。然而
为简单起见,该类被直接使用。此示例使用 Batch 的域语言中的示例。第一个
参数是 ,它是包含 .第二个参数表示作业名称。最后一个参数 , 将转换为 类型为 的对象。main
EndOfDay
endOfDayJob.xml
Job
endOfDay,
schedule.date=2007-05-05,java.time.LocalDate
JobParameter
java.time.LocalDate
以下示例显示了 in XML 的示例配置:endOfDay
<job id="endOfDay">
<step id="step1" parent="simpleStep" />
</job>
<!-- Launcher details removed for clarity -->
<beans:bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.TaskExecutorJobLauncher" />
在大多数情况下,您需要使用 manifest 在 jar 中声明您的类。然而
为简单起见,该类被直接使用。此示例使用 Batch 的域语言中的示例。第一个
argument 是 ,这是完全限定的类名
添加到包含 Job 的配置类中。第二个参数 , 表示
作业名称。最后一个参数 , 被转换
转换为类型为 .main
EndOfDay
io.spring.EndOfDayJobConfiguration
endOfDay
schedule.date=2007-05-05,java.time.LocalDate
JobParameter
java.time.LocalDate
以下示例显示了 在 Java 中的配置示例:endOfDay
@Configuration
@EnableBatchProcessing
public class EndOfDayJobConfiguration {
@Bean
public Job endOfDay(JobRepository jobRepository, Step step1) {
return new JobBuilder("endOfDay", jobRepository)
.start(step1)
.build();
}
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.tasklet((contribution, chunkContext) -> null, transactionManager)
.build();
}
}
前面的示例过于简单,因为
通常在 Spring Batch 中运行批处理作业,但它用于显示两个主要的
的要求 : 和 .CommandLineJobRunner
Job
JobLauncher
退出代码
从命令行启动批处理作业时,企业
经常使用 scheduler。大多数调度程序都相当愚蠢,只能工作
在流程级别。这意味着他们只知道一些
操作系统进程(例如它们调用的 shell 脚本)。
在这种情况下,与调度程序通信的唯一方法
关于作业的成功或失败是通过返回代码。一个
return code 是进程返回给调度程序的数字
以指示运行结果。在最简单的情况下,0 是
成功,1 是失败。但是,可能还有更复杂的
场景,例如“如果作业 A 返回 4,则启动作业 B,如果作业返回 5,则启动作业 B
下班 C。这种类型的行为在调度程序级别配置,
但重要的是,像 Spring Batch 这样的处理框架
提供一种方法来返回退出代码的数字表示形式
对于特定的批处理作业。在 Spring Batch 中,这是封装的
在 中,在 more
详情见第 5 章。为了讨论退出代码,
唯一需要知道的是,an 有一个 exit code 属性,该属性是
设置,并作为从 .将转换此字符串值
使用界面更改为数字:ExitStatus
ExitStatus
JobExecution
JobLauncher
CommandLineJobRunner
ExitCodeMapper
public interface ExitCodeMapper {
public int intValue(String exitCode);
}
an 的基本协定是,给定一个字符串 exit
code 时,将返回一个数字表示形式。默认的
Job Runner 使用的实现是返回 0 表示完成、1 表示一般错误和 2 表示任何作业的实现
运行器错误,例如无法在提供的上下文中找到 A。如果有更多
complex 的 3 个值,则自定义
接口的实现
必须提供。因为 是创建
因此,AN AND 不能是
'wired together' 时,任何需要覆盖的值都必须是
自动装配。这意味着,如果在 、
在创建上下文后,它会注入到 Runner 中。都
需要做的是提供你自己的
作为根级 Bean 进行加载,并确保它是
跑步者。ExitCodeMapper
SimpleJvmExitCodeMapper
Job
ExitCodeMapper
CommandLineJobRunner
ApplicationContext
ExitCodeMapper
BeanFactory
ExitCodeMapper
ApplicationContext
从 Web 容器中运行作业
从历史上看,离线处理(例如批处理作业)一直是
从命令行启动,如前所述。但是,有
在许多情况下,从 启动
一个更好的选择。许多此类用例包括报告、临时作业
running 和 Web 应用程序支持。因为批处理作业(根据定义)
运行时间长,最关心的是启动
job 异步:HttpRequest
在这种情况下,控制器是 Spring MVC 控制器。请参阅
Spring Framework 参考指南,了解有关 Spring MVC 的更多信息。
控制器使用已配置为异步启动的 来启动 一个,该
立即返回一个 .它可能仍在运行。但是,此
非阻塞行为允许控制器立即返回,这
在处理 .以下清单
显示了一个例子:Job
JobLauncher
JobExecution
Job
HttpRequest
@Controller
public class JobLauncherController {
@Autowired
JobLauncher jobLauncher;
@Autowired
Job job;
@RequestMapping("/jobLauncher.html")
public void handle() throws Exception{
jobLauncher.run(job, new JobParameters());
}
}
高级元数据用法
到目前为止,和 接口都是
讨论。它们共同代表了 Job 和 Basic 的简单启动
批处理域对象的 CRUD 操作:JobLauncher
JobRepository
A 使用 创建新对象并运行它们。 和实现
以后对基本更新使用相同的
在 .
基本操作足以满足简单的场景。但是,在大批量
具有数百个批处理作业和复杂调度的环境
要求,则需要对元数据进行更高级的访问:JobLauncher
JobRepository
JobExecution
Job
Step
JobRepository
Job
和 接口,这些接口将进行讨论
在接下来的部分中,添加用于查询和控制元数据的其他功能。JobExplorer
JobOperator
查询存储库
在任何高级功能之前,最基本的需求是能够
查询存储库中的现有执行。此功能是
由 interface 提供:JobExplorer
public interface JobExplorer {
List<JobInstance> getJobInstances(String jobName, int start, int count);
JobExecution getJobExecution(Long executionId);
StepExecution getStepExecution(Long jobExecutionId, Long stepExecutionId);
JobInstance getJobInstance(Long instanceId);
List<JobExecution> getJobExecutions(JobInstance jobInstance);
Set<JobExecution> findRunningJobExecutions(String jobName);
}
从其方法签名中可以明显看出,是
的 ,并且与 一样,它可以通过使用
工厂 Bean 的 Bean 中。JobExplorer
JobRepository
JobRepository
以下示例显示了如何在 XML 中配置 a:JobExplorer
<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" />
以下示例演示如何在 Java 中配置 a:JobExplorer
...
// This would reside in your DefaultBatchConfiguration extension
@Bean
public JobExplorer jobExplorer() throws Exception {
JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
factoryBean.setDataSource(this.dataSource);
return factoryBean.getObject();
}
...
在本章的前面部分,我们注意到您可以修改表前缀
的允许不同的版本或架构。因为
对于相同的表,它还需要能够设置前缀。JobRepository
JobExplorer
以下示例演示如何在 XML 中设置 a 的表前缀:JobExplorer
<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:tablePrefix="SYSTEM."/>
以下示例显示了如何在 Java 中为 a 设置表前缀:JobExplorer
...
// This would reside in your DefaultBatchConfiguration extension
@Bean
public JobExplorer jobExplorer() throws Exception {
JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
factoryBean.setDataSource(this.dataSource);
factoryBean.setTablePrefix("SYSTEM.");
return factoryBean.getObject();
}
...
JobRegistry (作业注册表)
A(及其父接口 )不是必需的,但可以是
如果要跟踪上下文中可用的作业,则很有用。它也是
在创建作业时,用于在应用程序上下文中集中收集作业
其他位置(例如,在子上下文中)。您还可以使用自定义实施
操作已注册作业的名称和其他属性。
框架只提供了一个实现,它基于一个简单的
从 Job Name 映射到 Job Instance。JobRegistry
JobLocator
JobRegistry
以下示例显示了如何包含 for a for a job defined in XML:JobRegistry
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
使用 时,将为您提供 a。
以下示例显示如何配置您自己的 :@EnableBatchProcessing
JobRegistry
JobRegistry
...
// This is already provided via the @EnableBatchProcessing but can be customized via
// overriding the bean in the DefaultBatchConfiguration
@Override
@Bean
public JobRegistry jobRegistry() throws Exception {
return new MapJobRegistry();
}
...
您可以通过以下两种方式之一填充 a:使用
Bean 后处理器或使用 registrar 生命周期组件。即将来临
各节介绍了这两种机制。JobRegistry
JobRegistryBeanPostProcessor
这是一个 bean 后处理器,可以在创建所有作业时注册它们。
以下示例显示了如何为 job 添加
在 XML 中定义:JobRegistryBeanPostProcessor
<bean id="jobRegistryBeanPostProcessor" class="org.spr...JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>
以下示例显示了如何为 job 添加
在 Java 中定义:JobRegistryBeanPostProcessor
@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}
尽管并非绝对必要,但
example 已被赋予一个,以便它可以包含在 Child 中
contexts(例如,作为父 Bean 定义)并导致创建所有作业
那里也会自动注册。id
自动作业注册器
这是一个生命周期组件,用于创建子上下文并从中注册作业
上下文。这样做的一个好处是,虽然
子上下文在 Registry 中仍然必须是全局唯一的,它们的依赖项
可以有 “natural” 名称。因此,例如,您可以创建一组 XML 配置文件
每个 Job 只有一个 Job ,但 an 的定义不同,其中
相同的 Bean 名称,例如 .如果所有这些文件都导入到同一上下文中,则
Reader 定义会相互冲突并覆盖,但是,使用 Automatic
registrar 的 intent 和未加密的 intent 的 x这使得集成
应用程序的单独模块。ItemReader
reader
以下示例显示了如何包含定义的 for a job defined
在 XML 中:AutomaticJobRegistrar
<bean class="org.spr...AutomaticJobRegistrar">
<property name="applicationContextFactories">
<bean class="org.spr...ClasspathXmlApplicationContextsFactoryBean">
<property name="resources" value="classpath*:/config/job*.xml" />
</bean>
</property>
<property name="jobLoader">
<bean class="org.spr...DefaultJobLoader">
<property name="jobRegistry" ref="jobRegistry" />
</bean>
</property>
</bean>
以下示例显示了如何包含定义的 for a job defined
在 Java 中:AutomaticJobRegistrar
@Bean
public AutomaticJobRegistrar registrar() {
AutomaticJobRegistrar registrar = new AutomaticJobRegistrar();
registrar.setJobLoader(jobLoader());
registrar.setApplicationContextFactories(applicationContextFactories());
registrar.afterPropertiesSet();
return registrar;
}
registrar 有两个必需属性:一个数组(从
方便的工厂 Bean)和 .负责管理子上下文的生命周期,并且
在 中注册作业。ApplicationContextFactory
JobLoader
JobLoader
JobRegistry
的
负责创建子上下文。最常见的用法
是(如前面的示例所示)来使用 .其中之一
这个工厂的特点是,默认情况下,它会复制一些
configuration down 从 parent context 到 child。因此,对于
实例,则无需重新定义 or AOP
配置,前提是它应与
父母。ApplicationContextFactory
ClassPathXmlApplicationContextFactory
PropertyPlaceholderConfigurer
您可以在
与 a 结合使用(只要您也使用 )。
例如,如果有工作,这可能是可取的
在主父上下文和子上下文中定义
地点。AutomaticJobRegistrar
JobRegistryBeanPostProcessor
DefaultJobLoader
JobOperator (作业操作员)
如前所述,它提供对元数据的 CRUD 操作,并且 提供对
元数据。但是,这些操作在一起使用时最有用
执行常见监控任务,例如停止、重新启动或
总结 Job,这通常是由 Batch Operator 完成的。Spring Batch
在界面中提供了以下类型的操作:JobRepository
JobExplorer
JobOperator
public interface JobOperator {
List<Long> getExecutions(long instanceId) throws NoSuchJobInstanceException;
List<Long> getJobInstances(String jobName, int start, int count)
throws NoSuchJobException;
Set<Long> getRunningExecutions(String jobName) throws NoSuchJobException;
String getParameters(long executionId) throws NoSuchJobExecutionException;
Long start(String jobName, String parameters)
throws NoSuchJobException, JobInstanceAlreadyExistsException;
Long restart(long executionId)
throws JobInstanceAlreadyCompleteException, NoSuchJobExecutionException,
NoSuchJobException, JobRestartException;
Long startNextInstance(String jobName)
throws NoSuchJobException, JobParametersNotFoundException, JobRestartException,
JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException;
boolean stop(long executionId)
throws NoSuchJobExecutionException, JobExecutionNotRunningException;
String getSummary(long executionId) throws NoSuchJobExecutionException;
Map<Long, String> getStepExecutionSummaries(long executionId)
throws NoSuchJobExecutionException;
Set<String> getJobNames();
}
上述操作表示来自许多不同接口的方法,例如 、 、 和 。因此,
提供的 () 实现具有许多依赖项。JobLauncher
JobRepository
JobExplorer
JobRegistry
JobOperator
SimpleJobOperator
以下示例显示了 XML 中的典型 bean 定义:SimpleJobOperator
<bean id="jobOperator" class="org.spr...SimpleJobOperator">
<property name="jobExplorer">
<bean class="org.spr...JobExplorerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
</property>
<property name="jobRepository" ref="jobRepository" />
<property name="jobRegistry" ref="jobRegistry" />
<property name="jobLauncher" ref="jobLauncher" />
</bean>
以下示例显示了 Java 中的典型 bean 定义:SimpleJobOperator
/**
* All injected dependencies for this bean are provided by the @EnableBatchProcessing
* infrastructure out of the box.
*/
@Bean
public SimpleJobOperator jobOperator(JobExplorer jobExplorer,
JobRepository jobRepository,
JobRegistry jobRegistry,
JobLauncher jobLauncher) {
SimpleJobOperator jobOperator = new SimpleJobOperator();
jobOperator.setJobExplorer(jobExplorer);
jobOperator.setJobRepository(jobRepository);
jobOperator.setJobRegistry(jobRegistry);
jobOperator.setJobLauncher(jobLauncher);
return jobOperator;
}
从版本 5.0 开始,注解会自动注册一个作业操作员 Bean
在应用程序上下文中。@EnableBatchProcessing
如果您在作业存储库上设置了表前缀,请不要忘记在作业资源管理器中也设置它。 |
JobParametersIncrementer (作业参数增量器)
上的大多数方法都是
一目了然,您可以在界面的 Javadoc 中找到更详细的解释。但是,该方法值得注意。这
方法始终启动 .
如果 a 中存在严重问题并且需要从头开始,这将非常有用。与(需要一个触发 new 的新对象)不同,如果参数与
任何前面的参数集,该方法都使用 Tied to 来强制 to a
新建实例:JobOperator
startNextInstance
Job
JobExecution
Job
JobLauncher
JobParameters
JobInstance
startNextInstance
JobParametersIncrementer
Job
Job
public interface JobParametersIncrementer {
JobParameters getNext(JobParameters parameters);
}
的合约是
给定一个 JobParameters 对象,它通过增加它可能包含的任何必要值来返回 “next” 对象。这
策略很有用,因为框架无法知道
将其设为“下一个”的更改
实例。例如,如果 中的唯一值是 date 和 next 实例
应该创建,该值应增加 1 天或 1
周(例如,如果工作是每周)?任何
有助于识别 、 的数值
如下例所示:JobParametersIncrementer
JobParameters
JobParameters
JobParameters
Job
public class SampleIncrementer implements JobParametersIncrementer {
public JobParameters getNext(JobParameters parameters) {
if (parameters==null || parameters.isEmpty()) {
return new JobParametersBuilder().addLong("run.id", 1L).toJobParameters();
}
long id = parameters.getLong("run.id",1L) + 1;
return new JobParametersBuilder().addLong("run.id", id).toJobParameters();
}
}
在此示例中,键为
区分。如果传入的值为 null,则可以为
假设 以前从未运行
因此,可以返回其初始状态。但是,如果不是,则旧的
value 被获取,递增 1 并返回。run.id
JobInstances
JobParameters
Job
对于在 XML 中定义的作业,您可以通过命名空间中的属性将 incrementer 与 a 关联,如下所示:Job
incrementer
<job id="footballJob" incrementer="sampleIncrementer">
...
</job>
对于在 Java 中定义的作业,您可以通过构建器中提供的方法将 incrementer 与 关联,如下所示:Job
incrementer
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.incrementer(sampleIncrementer())
...
.build();
}
停止作业
最常见的用例之一是正常停止
工作:JobOperator
Set<Long> executions = jobOperator.getRunningExecutions("sampleJob");
jobOperator.stop(executions.iterator().next());
关闭不是立即的,因为没有办法强制
立即关闭,尤其是在执行当前处于
开发人员代码,例如
商业服务。但是,一旦控制权返回到
框架中,它将当前状态设置为 ,保存它,并执行相同的操作
对于整理前。StepExecution
BatchStatus.STOPPED
JobExecution
中止作业
任务执行可以是
restarted (如果 是可重启的)。状态为 的任务执行 Framework 无法重新启动。
状态也用于步骤
executions 在重新启动的任务执行中将其标记为可跳过。如果
作业正在运行,并遇到在上一个失败的作业执行中标记的步骤,则
继续执行下一步(由 Job Flow 定义确定
和步骤执行退出状态)。FAILED
Job
ABANDONED
ABANDONED
ABANDONED
如果进程已终止( 或服务器
failure),该作业当然不会运行,但
无法知道,因为在过程结束之前没有人告诉它。你
必须手动告诉它您知道执行失败
或应被视为已中止(将其状态更改为 或 )。这是
一个商业决策,没有办法自动化它。更改
status 设置为仅当它是可重启的并且您知道重启数据有效时。kill -9
JobRepository
FAILED
ABANDONED
FAILED