首页 > 其他分享 >Spring Batch -配置和运行作业

Spring Batch -配置和运行作业

时间:2022-12-16 10:06:56浏览次数:41  
标签:XML 示例 Spring 配置 作业 Batch Job new

Spring Batch -配置和运行作业_批处理

在域部分,整体 讨论了体系结构设计,使用下图作为 指导:

Spring Batch -配置和运行作业_批处理_02

图1.批量构造型

虽然这个对象看起来很简单 容器的步骤,您必须了解许多配置选项。 此外,您必须考虑许多选项 如何运行 a 及其元数据如何运行 在该运行期间存储。本章介绍各种配置 的选项和运行时关注的问题。​​Job​​​​Job​​​​Job​

配置作业

可重启性

执行批处理作业时的一个关键问题涉及 重新 启动。如果特定 .理想情况下,所有作业都应该能够启动 从他们离开的地方开始,但在某些情况下这是不可能的。在这种情况下,完全由开发人员来确保创建新的 ​​JobInstance​​。但是,Spring Batch确实提供了一些帮助。如果 a 永远不应该 重新启动但应始终作为新的一部分运行,您可以设置 可重新启动的属性到 。​​Job​​​​Job​​​​JobExecution​​​​JobInstance​​​​Job​​​​JobInstance​​​​false​

下面的示例演示如何在 XML 中将字段设置为 :​​restartable​​​​false​

例 1.XML 配置

<job id="footballJob" restartable="false">
...
</job>

以下示例演示如何在 Java 中将字段设置为 :​​restartable​​​​false​

例 2.爪哇配置

@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.preventRestart()
...
.build();
}

换句话说,设置为 表示“这不支持再次启动”。重新启动不是 可重新启动会导致 被扔掉。 以下 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
}

第一次尝试为不可重新启动的 作业不会导致任何问题。然而,第二个 尝试抛出 .​​JobExecution​​​​JobRestartException​

拦截作业执行

在执行过程中,通知各种 事件,以便可以运行自定义代码。 通过在适当的时间调用 来允许这样做:​​Job​​​​SimpleJob​​​​JobListener​

public interface JobExecutionListener {

void beforeJob(JobExecution jobExecution);

void afterJob(JobExecution jobExecution);
}

您可以通过在作业上设置侦听器来添加到 。​​JobListeners​​​​SimpleJob​

下面的示例演示如何将侦听器元素添加到 XML 作业定义:

例 3.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 作业定义:

例 4.爪哇配置

@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​​​​Job​​​​Job​

在下面的示例中,是一个抽象定义,它仅定义 听众。()是混凝土 从中继承侦听器列表并合并的定义 它有自己的侦听器列表,以生成具有两个侦听器和一个 () 的侦听器。​​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>

有关更多详细信息,请参阅从父步骤继承部分。

作业参数验证器

在 XML 命名空间中声明的作业或使用 的任何子类可以选择在 处声明作业参数的验证程序 运行。例如,当您需要断言作业时,这很有用 以其所有必需参数启动。有一个可以用来约束组合 简单的必需和可选参数。对于更复杂的 约束,您可以自己实现接口。​​AbstractJob​​​​DefaultJobParametersValidator​

爪哇配置

Spring 3带来了使用Java而不是XML配置应用程序的能力。截至 Spring 批处理 2.2.0,您可以使用相同的 Java 配置来配置批处理作业。 基于 Java 的配置有三个组件:注释和两个构建器。​​@EnableBatchProcessing​

批注的工作方式与 春天的家庭。在本例中,提供 构建批处理作业。在此基本配置中,和 的实例 创建,除了许多可以自动连线的 bean 之外:​​@EnableBatchProcessing​​​​@Enable*​​​​@EnableBatchProcessing​​​​StepScope​​​​JobScope​

  • ​JobRepository​​:一个叫jobRepository
  • ​JobLauncher​​:一个叫jobLauncher
  • ​JobRegistry​​:一个叫jobRegistry
  • ​JobExplorer​​:一个叫jobExplorer
  • ​JobOperator​​:一个叫jobOperator

默认实现提供前面列表中提到的 bean,并要求在上下文中将 a 和 a 作为 bean 提供。数据源和事务 管理器由 和 实例使用。默认情况下,将使用命名的数据源和命名的事务管理器。您可以使用以下方法自定义这些 Bean 中的任何一个 批注的属性。以下示例演示如何提供 自定义数据源和事务管理器:​​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);
}

public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}

}


只有一个配置类需要具有注释。一次 你有一个用它注释的类,你拥有前面描述的所有配置。​​@EnableBatchProcessing​


从 v5.0 开始,这是一种配置基础基础设施 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();
}

}

数据源和事务管理器将从应用程序上下文中解析 并在作业存储库和作业资源管理器上设置。您可以自定义配置 通过覆盖所需的 setter 来覆盖任何基础结构 Bean。以下示例 演示如何自定义字符编码,例如:

@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​不应与 一起使用。你应该 要么使用通过 配置 Spring Batch 的声明式方式, 或者使用扩展的编程方式,但不能同时使用 同一时间。​​DefaultBatchConfiguration​​​​@EnableBatchProcessing​​​​DefaultBatchConfiguration​


配置作业存储库

使用 时,将向您提供 。 本节介绍如何配置自己的配置。​​@EnableBatchProcessing​​​​JobRepository​

如前所述,JobRepository 用于各种持久化的基本 CRUD 操作 Spring Batch 中的域对象,例如 和 . 许多主要的框架功能(如 、 和 )都需要它。​​JobExecution​​​​StepExecution​​​​JobLauncher​​​​Job​​​​Step​

批处理命名空间抽象出实现及其协作者的许多实现细节。但是,仍然有一些 可用的配置选项,如以下示例所示:​​JobRepository​

例 5.XML 配置

<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​

除了 和 之外,不需要前面列出的任何配置选项。 如果未设置,则前面显示的默认值 被使用。这 最大长度默认为 ,即 示例架构脚本中长列的长度​​dataSource​​​​transactionManager​​​​varchar​​​​2500​​​​VARCHAR​

作业存储库的事务配置

如果使用命名空间或提供的命名空间,则事务建议是 围绕存储库自动创建。这是为了确保批处理元数据, 包括故障后重新启动所需的状态,将正确保留。 如果存储库方法不是,则框架的行为没有很好地定义 事务。指定方法属性中的隔离级别 分别确保在启动作业时,如果两个进程尝试启动 同一时间做同样的工作,只有一个人成功。该的默认隔离级别 方法是 ,这是相当激进的。 通常同样有效 井。 如果两个进程不太可能在此发生冲突,则没关系 道路。但是,由于对该方法的调用非常短,因此只要数据库平台支持它,就不太可能导致问题。但是,你 可以覆盖此设置。​​FactoryBean​​​​create*​​​​SERIALIZABLE​​​​READ_COMMITTED​​​​READ_UNCOMMITTED​​​​create*​​​​SERIALIZED​

下面的示例演示如何在 XML 中重写隔离级别:

例 6.XML 配置

<job-repository id="jobRepository"
isolation-level-for-create="REPEATABLE_READ" />

以下示例演示如何在 Java 中覆盖隔离级别:

例 7.爪哇配置

@Configuration
@EnableBatchProcessing(isolationLevelForCreate = "ISOLATION_REPEATABLE_READ")
public class MyJobConfiguration {

// job definition

}

如果未使用命名空间,则还必须配置 使用 AOP 的存储库的事务行为。

以下示例显示如何配置存储库的事务行为 在 XML 中:

例 8.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>

您几乎可以按原样使用前面的片段,几乎无需更改。还记得 包括适当的命名空间声明,并确保 和(或整个 Spring)都在类路径上。​​spring-tx​​​​spring-aop​

以下示例显示如何配置存储库的事务行为 在爪哇中:

例 9.爪哇配置

@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 中更改表前缀:

例 10.XML 配置

<job-repository id="jobRepository"
table-prefix="SYSTEM.TEST_" />

以下示例演示如何在 Java 中更改表前缀:

例 11.爪哇配置

@Configuration
@EnableBatchProcessing(tablePrefix = "SYSTEM.TEST_")
public class MyJobConfiguration {

// job definition

}

鉴于上述更改,对元数据表的每个查询都以 为前缀。 称为 。​​SYSTEM.TEST_​​​​BATCH_JOB_EXECUTION​​​​SYSTEM.TEST_JOB_EXECUTION​


只有表前缀是可配置的。表名和列名不是。


存储库中的非标准数据库类型

如果使用的数据库平台不在支持的平台列表中,则 如果 SQL 变体足够接近,则可以使用受支持的类型之一。待办事项 这样,您可以使用 RAW 而不是命名空间快捷方式和 使用它可将数据库类型设置为最接近的匹配项。​​JobRepositoryFactoryBean​

下面的示例演示如何使用 设置数据库类型 到 XML 中最接近的匹配项:​​JobRepositoryFactoryBean​

例 12.XML 配置

<bean id="jobRepository" class="org...JobRepositoryFactoryBean">
<property name="databaseType" value="db2"/>
<property name="dataSource" ref="dataSource"/>
</bean>

下面的示例演示如何使用 设置数据库类型 到爪哇中最接近的匹配项:​​JobRepositoryFactoryBean​

例 13.爪哇配置

@Bean
public JobRepository jobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(dataSource);
factory.setDatabaseType("db2");
factory.setTransactionManager(transactionManager);
return factory.getObject();
}

如果未指定数据库类型,则 尝试 从 中自动检测数据库类型。 平台之间的主要区别是 主要由主键递增的策略来说明,所以 通常还需要覆盖 以及(通过使用标准之一 来自 Spring 框架的实现)。​​JobRepositoryFactoryBean​​​​DataSource​​​​incrementerFactory​

如果即使这样也不起作用,或者您没有使用 RDBMS,则 唯一的选择可能是实现所依赖的各种接口 上并以正常的弹簧方式手动连接一个。​​Dao​​​​SimpleJobRepository​

配置作业启动器

当您使用 时,会为您提供 。 本节介绍如何配置自己的配置。​​@EnableBatchProcessing​​​​JobRegistry​

该接口最基本的实现是 . 它唯一需要的依赖项是 a(获取执行所需的)。​​JobLauncher​​​​TaskExecutorJobLauncher​​​​JobRepository​

下面的示例演示 XML 中的 :​​TaskExecutorJobLauncher​

例 14.XML 配置

<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.TaskExecutorJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>

以下示例显示了 Java 中的 a:​​TaskExecutorJobLauncher​

例 15.爪哇配置

...
@Bean
public JobLauncher jobLauncher() throws Exception {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
...

一旦获得 JobExecution,它就会传递给 的执行方法,最终将 返回给调用方,作为 下图显示:​​Job​​​​JobExecution​

Spring Batch -配置和运行作业_批处理_03

图2.作业启动器序列

该序列很简单,从调度程序启动时效果很好。然而 尝试从 HTTP 请求启动时出现问题。在这种情况下,启动 需要异步完成,以便立即返回到其 访客。这是因为保持 HTTP 请求打开状态不是很好的做法 长时间运行的进程(如批处理作业)所需的时间量。下图显示了 示例序列:​​TaskExecutorJobLauncher​

Spring Batch -配置和运行作业_批处理_04

图3.异步作业启动器序列

您可以通过配置 .​​TaskExecutorJobLauncher​​​​TaskExecutor​

以下 XML 示例将 配置为立即返回:​​TaskExecutorJobLauncher​

例 16.XML 配置

<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 示例将 配置为立即返回:​​TaskExecutorJobLauncher​

例 17.爪哇配置

@Bean
public JobLauncher jobLauncher() {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
jobLauncher.setJobRepository(jobRepository());
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}

您可以使用 spring 接口的任何实现来控制作业的异步方式 执行。​​TaskExecutor​

运行作业

启动批处理作业至少需要两件事:要启动的和 .两者都可以包含在同一个 上下文或不同的上下文。例如,如果您从 命令行,为每个 .因此,每 工作有自己的.但是,如果 您从 范围内的 Web 容器中运行,通常有一个(为异步作业配置) 启动),多个请求调用以启动其作业。​​Job​​​​JobLauncher​​​​Job​​​​JobLauncher​​​​HttpRequest​​​​JobLauncher​

从命令行运行作业

如果要从企业运行作业 调度程序,命令行是主界面。这是因为 大多数调度程序(Quartz除外,除非使用)直接与操作系统一起工作 进程,主要由 shell 脚本启动。有很多种方式 启动 shell 脚本之外的 Java 进程,例如 Perl、Ruby 或 甚至构建工具,例如Ant或Maven。但是,因为大多数人 熟悉 shell 脚本,此示例重点介绍它们。​​NativeJob​

The CommandLineJobRunner

因为启动作业的脚本必须启动 Java 虚拟机,需要一个带有方法来操作的类 作为主入口点。Spring Batch 提供了一个实现 用于此目的:。注意 这只是引导应用程序的一种方法。有 启动 Java 进程的方法很多,这个类绝不应该是 被视为确定性。执行四个任务:​​main​​​​CommandLineJobRunner​​​​CommandLineJobRunner​

  • 加载相应的 .ApplicationContext
  • 将命令行参数解析为 .JobParameters
  • 根据参数找到相应的作业。
  • 使用应用程序上下文中提供的 来启动作业。JobLauncher

所有这些任务都只通过传入的参数完成。 下表描述了所需的参数:

表 1.CommandLineJobRunner 参数

​jobPath​

用于 创建一个 .此文件 应包含运行完整 .​​ApplicationContext​​​​Job​

​jobName​

要运行的作业的名称。

必须传入这些参数,路径在前,名称在后。所有参数 这些被认为是作业参数后,被变成一个对象, 并且必须采用 的格式。​​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


默认情况下,使用 隐式转换 用于标识作业参数的键/值对。但是,您可以显式指定 哪些作业参数分别通过 or 后缀来标识,哪些不是通过后缀来标识它们。​​CommandLineJobRunner​​​​DefaultJobParametersConverter​​​​true​​​​false​



在以下示例中,是标识作业参数,而不是:​​schedule.date​​​​vendor.id​


<bash$ java CommandLineJobRunner endOfDayJob.xml endOfDay \
schedule.date=2007-05-05,java.time.LocalDate,true \
vendor.id=123,java.lang.Long,false
<bash$ java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay \
schedule.date=2007-05-05,java.time.LocalDate,true \
vendor.id=123,java.lang.Long,false

您可以使用自定义 .​​JobParametersConverter​

前面的示例过于简单化,因为对 通常在Spring Batch中运行批处理作业,但它用于显示两个主要的 的要求: 和 。​​CommandLineJobRunner​​​​Job​​​​JobLauncher​

退出代码

从命令行启动批处理作业时,企业 经常使用调度程序。大多数调度程序都相当愚蠢,只能工作 在流程级别。这意味着他们只知道一些 操作系统进程(例如它们调用的 shell 脚本)。 在这种情况下,与调度程序通信的唯一方法 关于作业的成功或失败是通过返回代码。一个 返回码是进程返回给调度程序的数字 以指示运行的结果。在最简单的情况下,0 是 成功,1 是失败。但是,可能会有更复杂的 方案,例如“如果作业 A 返回 4,则启动作业 B,如果返回 5,则踢 离开工作C。这种类型的行为是在调度程序级别配置的, 但重要的是,像Spring Batch这样的处理框架 提供一种返回退出代码的数字表示形式的方法 对于特定的批处理作业。在春季批次中,这是封装的 在 中,在 中涵盖更多 详见第5章。为了讨论退出代码, 唯一需要知道的重要一点是 AN 具有 由框架(或开发人员)设置,并作为从 返回的一部分返回。转换此字符串值 通过使用接口到数字:​​ExitStatus​​​​ExitStatus​​​​JobExecution​​​​JobLauncher​​​​CommandLineJobRunner​​​​ExitCodeMapper​

public interface ExitCodeMapper {

public int intValue(String exitCode);

}

一个的基本合约是,给定一个字符串退出 代码,将返回数字表示形式。默认 作业运行程序使用的实现是 返回 0 表示完成,1 表示一般错误,2 表示任何作业 运行器错误,例如无法在提供的上下文中找到 a。如果还有更多 需要比上述三个值复杂,自定义 接口的实现 必须提供。因为 是创建 因此,不能是 “连接在一起”,任何需要覆盖的值都必须 自动连线。这意味着,如果在 中找到 的实现, 创建上下文后,它将注入到运行器中。都 需要做的是提供你自己的是声明实现 作为根级 Bean,并确保它是由 跑步者。​​ExitCodeMapper​​​​SimpleJvmExitCodeMapper​​​​Job​​​​ExitCodeMapper​​​​CommandLineJobRunner​​​​ApplicationContext​​​​ExitCodeMapper​​​​BeanFactory​​​​ExitCodeMapper​​​​ApplicationContext​

从 Web 容器内运行作业

从历史上看,脱机处理(例如批处理作业)一直是 如前所述,从命令行启动。但是,有 从 IS 启动的许多情况 更好的选择。许多这样的用例包括报告、临时作业 运行和 Web 应用程序支持。因为批处理作业(根据定义) 运行时间长,最重要的关注点是启动 异步作业:​​HttpRequest​

Spring Batch -配置和运行作业_XML_05

图4.来自 Web 容器的异步作业启动器序列

在这种情况下,控制器是Spring MVC控制器。请参阅的 Spring Framework Reference Guide for more about 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());
}
}

高级元数据用法

到目前为止,和 接口都是 讨论。它们共同代表了工作的简单启动和基本 批处理域对象的 CRUD 操作:​​JobLauncher​​​​JobRepository​

Spring Batch -配置和运行作业_XML_06

图5.作业存储库

A 使用 创建新对象并运行它们。 和实施 稍后对基本更新使用相同的方法 在运行 . 基本操作足以满足简单方案的需求。但是,在大批量中 具有数百个批处理作业和复杂调度的环境 要求,需要对元数据进行更高级的访问:​​JobLauncher​​​​JobRepository​​​​JobExecution​​​​Job​​​​Step​​​​JobRepository​​​​Job​

Spring Batch -配置和运行作业_Java_07

图6.高级作业存储库访问

和接口,将讨论 在接下来的部分中,添加用于查询和控制元数据的其他功能。​​JobExplorer​​​​JobOperator​

查询存储库

在任何高级功能之前,最基本的需求是能够 查询存储库中的现有执行。此功能是 接口提供:​​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);
}

从其方法签名中可以明显看出,是只读版本的 和,并且与 一样,可以使用 工厂豆。​​JobExplorer​​​​JobRepository​​​​JobRepository​

下面的示例演示如何在 XML 中配置 :​​JobExplorer​

例 18.XML 配置

<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" />

以下示例显示了如何在 Java 中配置 :​​JobExplorer​

例 19.爪哇配置

...
// 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 中为 设置表前缀:​​JobExplorer​

例 20.XML 配置

<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:tablePrefix="SYSTEM."/>

以下示例演示如何在 Java 中为 a 设置表前缀:​​JobExplorer​

例 21.爪哇配置

...
// 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();
}
...

工作注册表

A(及其父接口)不是必需的,但它可以是 如果要跟踪上下文中可用的作业,则很有用。它也是 用于在创建作业时在应用程序上下文中集中收集作业 其他地方(例如,在子环境中)。您还可以使用自定义实现 以操作已注册作业的名称和其他属性。 框架只提供了一个实现,这是基于一个简单的 从作业名称映射到作业实例。​​JobRegistry​​​​JobLocator​​​​JobRegistry​

下面的示例演示如何为 XML 中定义的作业包含 :​​JobRegistry​

<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />

使用 时,将向您提供 。 以下示例演示如何配置您自己的:​​@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 后处理器或使用注册器生命周期组件。即将到来 各节介绍这两种机制。​​JobRegistry​

JobRegistryBeanPostProcessor

这是一个 Bean 后处理器,可以在创建作业时注册所有作业。

以下示例演示如何包含 for 作业 在 XML 中定义:​​JobRegistryBeanPostProcessor​

例 22.XML 配置

<bean id="jobRegistryBeanPostProcessor" class="org.spr...JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>

以下示例演示如何包含 for 作业 在爪哇中定义:​​JobRegistryBeanPostProcessor​

例 23.爪哇配置

@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}

虽然这不是绝对必要的,但后处理器在 示例已给出一个,以便它可以包含在子项中 上下文(例如,作为父 Bean 定义)并导致创建所有作业 那里也将自动注册。​​id​

AutomaticJobRegistrar

这是一个生命周期组件,用于创建子上下文并从这些上下文注册作业 创建上下文时的上下文。这样做的一个优点是,虽然作业名称 子上下文在注册表中仍然必须是全局唯一的,它们的依赖项 可以有“自然”名称。因此,例如,您可以创建一组 XML 配置文件 每个作业只有一个作业,但对 相同的 Bean 名称,例如 .如果所有这些文件都导入到同一上下文中, 读取器定义会相互冲突并覆盖彼此,但是,自动 注册商,这是可以避免的。这使得整合来自 应用程序的单独模块。​​ItemReader​​​​reader​

以下示例演示如何包含 for 定义的作业 在 XML 中:​​AutomaticJobRegistrar​

例 24.XML 配置

<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 定义的作业 在爪哇中:​​AutomaticJobRegistrar​

例 25.爪哇配置

@Bean
public AutomaticJobRegistrar registrar() {

AutomaticJobRegistrar registrar = new AutomaticJobRegistrar();
registrar.setJobLoader(jobLoader());
registrar.setApplicationContextFactories(applicationContextFactories());
registrar.afterPropertiesSet();
return registrar;

}

注册器有两个必需属性:数组 (从 前面示例中的方便工厂 Bean)和 .负责管理子上下文的生命周期和 在 中注册作业。​​ApplicationContextFactory​​​​JobLoader​​​​JobLoader​​​​JobRegistry​

这是 负责创建子上下文。最常见的用法 是(如前面的示例所示)使用 .其中之一 此工厂的功能是,默认情况下,它复制一些 配置从父上下文向下到子上下文。所以,对于 实例,则无需重新定义 或 AOP 子项中的配置,前提是它应与 父母。​​ApplicationContextFactory​​​​ClassPathXmlApplicationContextFactory​​​​PropertyPlaceholderConfigurer​

您可以在 与 a 结合(只要您还使用 )。 例如,如果有工作,这可能是可取的 在主父上下文和子上下文中定义 地点。​​AutomaticJobRegistrar​​​​JobRegistryBeanPostProcessor​​​​DefaultJobLoader​

作业操作员

如前所述,提供对元数据的 CRUD 操作,对元数据提供只读操作 元数据。但是,这些操作在一起使用时最有用 执行常见监视任务,例如停止、重新启动或 汇总作业,通常由批处理操作员完成。春季批次 在接口中提供以下类型的操作:​​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 中存在严重问题并且需要从头开始,这将非常有用。不像(这需要一个触发新对象的新对象),如果参数不同于 任何先前的参数集,该方法使用 绑定到 强制 到 a 新实例:​​JobOperator​​​​startNextInstance​​​​Job​​​​JobExecution​​​​Job​​​​JobLauncher​​​​JobParameters​​​​JobInstance​​​​startNextInstance​​​​JobParametersIncrementer​​​​Job​​​​Job​

public interface JobParametersIncrementer {

JobParameters getNext(JobParameters parameters);

}

的合同是 给定一个 JobParameters 对象,它通过递增可能包含的任何必要值来返回“下一个”对象。这 策略很有用,因为框架无法知道什么 更改使其成为“下一个” 实例。例如,如果 中的唯一值是日期和下一个实例 应该创建,如果该值增加一天或一天 周(例如,如果工作是每周)?对于任何 有助于识别 、 如以下示例所示:​​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();
}
}

在此示例中,键为 的值用于 区分。如果传入为空,则可以 假设以前从未运行过 因此,可以返回其初始状态。但是,如果没有,旧的 值被获取,递增 1,然后返回。​​run.id​​​​JobInstances​​​​JobParameters​​​​Job​

停止作业

最常见的用例之一是优雅地停止 工作:​​JobOperator​

Set<Long> executions = jobOperator.getRunningExecutions("sampleJob");
jobOperator.stop(executions.iterator().next());

关闭不是立即的,因为没有办法强制 立即关闭,尤其是在执行当前处于 框架无法控制的开发人员代码,例如 商务服务。但是,一旦控制权返回到 框架,它将当前状态设置为 ,保存它,并执行相同的操作 在完成之前。​​StepExecution​​​​BatchStatus.STOPPED​​​​JobExecution​

中止作业

作业执行可以是 已重新启动(如果 可重新启动)。状态为“框架无法重新启动”的作业执行。 状态也用于步骤 执行以在重新启动的作业执行中将其标记为可跳过。如果 作业正在运行,并且遇到在上一个失败的作业执行中标记的步骤,它 继续执行下一步(由作业流定义确定) 和步骤执行退出状态)。​​FAILED​​​​Job​​​​ABANDONED​​​​ABANDONED​​​​ABANDONED​

如果进程死亡(或服务器) 失败),作业当然不是在运行,而是有 无从得知,因为在过程死亡之前没有人告诉它。你 必须手动告诉它您知道执行失败 或应视为已中止(将其状态更改为 或 )。这是 一个业务决策,并且没有办法自动化它。更改 状态为仅当它可重新启动并且您知道重新启动数据有效时。​​kill -9​​​​JobRepository​​​​FAILED​​​​ABANDONED​​​​FAILED​

标签:XML,示例,Spring,配置,作业,Batch,Job,new
From: https://blog.51cto.com/u_15326439/5946745

相关文章

  • springMVC08(REST风格的“入门案例”)
    一、用REST风格,来演示"增、删、改、查"操作。1.1:增POST1.1.1:用PostMan测试:增POST:代码块@RequestMapping(value="/users",method=RequestMethod.POST)@R......
  • SpringMvc的基础
     首先SpringMvc是一款实现MVC模型的轻量级web框架,主要用在写那个controller也就是控制器,也就是表现层代码的书写,以前使用Servlet来写这个表现层,现在的话使用SpringMvc就......
  • Spring Boot
    SpringBoot技术分析与运用—抢购网项目在互联网兴起的时代,高可用、高性能和高可扩展性的项目架构方式将是一个必然趋势,而微服务则是目前最好的选择。微服务是更细粒度的......
  • 2.Spring Boot项目环境搭建
    2.1环境要求JDK1.7及以上版本,Maven3.2及以上版本,IDEA14及以上版本2.2搭建步骤第一步:打开IDEA,选择File,新建project或者module,弹出如图2.1所示的窗口   这里JDK默......
  • SpringCloud OpenFeign配置
    前言原生OpenFeign与SpringCloudOpenFeign在配置上有些区别,主要关注点在Contract、Encoder、Decoder的不同,而Contract最主要作用是对feignClient接口与方法上注解的解析......
  • Spring的事务传播机制
    参考资料:https://zhuanlan.zhihu.com/p/148504094什么是事务的传播简单的理解就是多个事务方法相互调用时,事务如何在这些方法间传播。举个栗子,方法A是一个事务的方法,......
  • Spring Security 安全框架入门原理及实战
    SpringSecurity入门原理及实战在web应用开发中,安全无疑是十分重要的,选择SpringSecurity来保护web应用是一个非常好的选择。SpringSecurity是spring项目之中的一个安全......
  • springMVC07(REST风格)
    一、REST风格的解释:(资源的访问形式)二、总结:2.1-REST:资源访问形式2.2-4个动作(GET、POST、PUT、DELETE)2.3-用"REST"风格开发,我们就叫"RESTful"......
  • springboot启动流程
    主要看下newSpringApplication逻辑和run方法逻辑:newSpringApplication逻辑:进入run方法后,会new一个SpringApplication对象,创建这个对象的构造函数做了一些准备工作,......
  • 随笔(八)『SpringBoot 解决ID和日期,前端显示不一致』
    packagecom.baihua.common.config;importcom.fasterxml.jackson.databind.DeserializationFeature;importcom.fasterxml.jackson.databind.ObjectMapper;importcom......