高级元数据使用
到目前为止,无论是JobLauncher
和JobRepository
接口已被
讨论。它们共同代表了作业的简单启动和基本
批处理域对象的 CRUD作:

一个JobLauncher
使用JobRepository
创建新的JobExecution
对象并运行它们。Job
和Step
实现
以后使用相同的JobRepository
对于基本更新
在运行期间的相同执行Job
.
对于简单的场景,基本作就足够了。但是,在大批量
具有数百个批处理作业和复杂调度的环境
要求,需要对元数据进行更高级的访问:

这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
,可以使用
工厂豆。
-
Java
-
XML
以下示例演示如何配置JobExplorer
在 Java 中:
...
// This would reside in your DefaultBatchConfiguration extension
@Bean
public JobExplorer jobExplorer() throws Exception {
JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
factoryBean.setDataSource(this.dataSource);
return factoryBean.getObject();
}
...
以下示例演示如何配置JobExplorer
在 XML 中:
<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" />
在本章前面,我们注意到您可以修改表前缀
的JobRepository
以允许不同的版本或模式。因为
这JobExplorer
适用于相同的表,它还需要能够设置前缀。
-
Java
-
XML
以下示例演示如何为JobExplorer
在 Java 中:
...
// 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();
}
...
以下示例演示如何为JobExplorer
在 XML 中:
<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:tablePrefix="SYSTEM."/>
作业注册表
一个JobRegistry
(及其父接口JobLocator
) 不是强制性的,但可以是
如果您想跟踪上下文中可用的作业,则很有用。它也是
对于在创建作业时在应用程序上下文中集中收集作业非常有用
其他地方(例如,在子上下文中)。您还可以使用自定义JobRegistry
实现
以作已注册作业的名称和其他属性。
该框架只提供了一种实现,它基于一个简单的
从作业名称映射到作业实例。
-
Java
-
XML
使用时@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();
}
...
以下示例演示如何包含JobRegistry
对于用 XML 定义的作业:
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
您可以填充JobRegistry
通过以下方式之一:通过使用
Bean 后处理器,或者通过使用智能初始化单例或使用
注册商生命周期组件。接下来的部分将介绍这些机制。
JobRegistryBean后处理器
这是一个 bean 后处理器,可以在创建作业时注册所有作业。
-
Java
-
XML
以下示例演示了如何包含JobRegistryBeanPostProcessor
为了工作
在 Java 中定义:
@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}
以下示例演示了如何包含JobRegistryBeanPostProcessor
为了工作
在 XML 中定义:
<bean id="jobRegistryBeanPostProcessor" class="org.spr...JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>
虽然不是绝对必要的,但
示例已给出一个id
这样就可以包含在子
上下文(例如,作为父 Bean 定义)并导致创建的所有作业
那里也会自动注册。
折旧
从 5.2 版本开始, |
JobRegistrySmart初始化单例
这是一个SmartInitializingSingleton
在作业注册表中注册所有单例作业。
-
Java
-
XML
以下示例显示如何定义JobRegistrySmartInitializingSingleton
在 Java 中:
@Bean
public JobRegistrySmartInitializingSingleton jobRegistrySmartInitializingSingleton(JobRegistry jobRegistry) {
return new JobRegistrySmartInitializingSingleton(jobRegistry);
}
以下示例显示如何定义JobRegistrySmartInitializingSingleton
在 XML 中:
<bean class="org.springframework.batch.core.configuration.support.JobRegistrySmartInitializingSingleton">
<property name="jobRegistry" ref="jobRegistry" />
</bean>
自动作业注册商
这是一个生命周期组件,用于创建子上下文并从这些上下文中注册作业
上下文创建时。这样做的一个好处是,虽然作业名称在
子上下文在注册表中仍然必须是全局唯一的,它们的依赖关系
可以有“自然”名称。因此,例如,您可以创建一组 XML 配置文件
每个只有一个作业,但都有不同的定义ItemReader
使用
相同的 bean 名称,例如reader
.如果所有这些文件都导入到同一个上下文中,
读者定义会相互冲突并覆盖彼此,但是,使用
registrar 的 registrar 中,避免了这一点。这使得集成贡献的作业变得更加容易
应用程序的单独模块。
-
Java
-
XML
以下示例演示了如何包含AutomaticJobRegistrar
对于已定义的作业
在 Java 中:
@Bean
public AutomaticJobRegistrar registrar() {
AutomaticJobRegistrar registrar = new AutomaticJobRegistrar();
registrar.setJobLoader(jobLoader());
registrar.setApplicationContextFactories(applicationContextFactories());
registrar.afterPropertiesSet();
return registrar;
}
以下示例演示了如何包含AutomaticJobRegistrar
对于已定义的作业
在 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>
注册商有两个必需属性:数组ApplicationContextFactory
(从
方便的工厂 bean)和JobLoader
.这JobLoader
负责管理子上下文的生命周期,并且
在JobRegistry
.
这ApplicationContextFactory
是
负责创建子上下文。最常见的用法
is(如前面的示例所示)使用ClassPathXmlApplicationContextFactory
.其中之一
这个工厂的特点是,默认情况下,它复制了一些
配置从父上下文向下到子上下文。所以,对于
实例,则无需重新定义PropertyPlaceholderConfigurer
或 AOP
配置,前提是它应该与
父母。
您可以使用AutomaticJobRegistrar
在
与JobRegistryBeanPostProcessor
(只要你还使用DefaultJobLoader
).
例如,如果有工作,这可能是可取的
在主父上下文和子上下文中定义
地点。
作业运算符
如前所述,该JobRepository
提供对元数据的 CRUD作,并且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
)有许多依赖项。
-
Java
-
XML
以下示例显示了SimpleJobOperator
在 Java 中:
/**
* 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;
}
以下示例显示了SimpleJobOperator
在 XML 中:
<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>
从 5.0 版本开始,@EnableBatchProcessing
注释自动注册作业运算符 Bean
在应用程序上下文中。
如果您在作业存储库上设置表前缀,请不要忘记在作业资源管理器上也设置它。 |
JobParameters递增器
大多数方法JobOperator
是 不言自明,您可以在接口的 Javadoc 中找到更详细的说明。但是,startNextInstance
方法值得注意。 这 方法总是启动一个新实例Job
. 如果存在严重问题,这将非常有用JobExecution
和Job
需要从头开始。 与JobLauncher
(这需要一个新的JobParameters
触发新JobInstance
),如果参数与任何先前的参数集不同,则startNextInstance
方法使用JobParametersIncrementer
绑定到Job
强制Job
设置为new 实例:
public interface JobParametersIncrementer {
JobParameters getNext(JobParameters parameters);
}
合同JobParametersIncrementer
是 给定一个 JobParameters 对象,它返回“next”JobParameters
对象,通过递增它可能包含的任何必要值。 这 策略很有用,因为框架无法知道什么更改JobParameters
让它成为“下一个” 实例。 例如,如果JobParameters
是一个日期,下一个实例应该创建,该值应该递增一天还是一天week(例如,如果作业是每周一次)?对于任何有助于识别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();
}
}
在此示例中,键为run.id
用于 区分JobInstances
. 如果JobParameters
传入为 null,则可以是假设Job
以前从未运行过因此,可以返回其初始状态。但是,如果没有,则获取旧的值,递增 1,然后返回。
-
Java
-
XML
对于用 Java 定义的作业,您可以将增量器与Job
通过incrementer
方法,如下所示:
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.incrementer(sampleIncrementer())
...
.build();
}
对于在 XML 中定义的作业,您可以将增量器与Job
通过incrementer
属性,如下所示:
<job id="footballJob" incrementer="sampleIncrementer">
...
</job>
停止作业
最常见的用例之一JobOperator
正在优雅地停止 工作:
Set<Long> executions = jobOperator.getRunningExecutions("sampleJob");
jobOperator.stop(executions.iterator().next());
关闭不是立即的,因为没有办法强制立即关闭,特别是如果执行当前在框架无法控制的开发人员代码中,例如业务服务。但是,一旦控制权返回给框架,它就会设置当前StepExecution
自BatchStatus.STOPPED
,保存它,并执行相同的作对于JobExecution
在完成之前。
中止工作
作业执行FAILED
可以restarted(如果Job
可重新启动)。状态为ABANDONED
框架无法重新启动。 这ABANDONED
status 也用于步骤executions 以将它们标记为在重新启动的作业执行中可跳过。如果作业正在运行并遇到已标记的步骤ABANDONED
在上一个失败的作业执行中,它继续执行下一步(由作业流定义和步骤执行退出状态确定)。
如果进程终止 (kill -9
或服务器failure),作业当然不是在运行,而是JobRepository
有无从得知,因为在进程消亡之前没有人告诉它。 你 必须手动告诉它你知道执行失败了或者应该被视为已中止(将其状态更改为FAILED
或ABANDONED
).这是
一个业务决策,并且没有办法将其自动化。将
status 设置为FAILED
仅当它是可重启的,并且你知道重启数据有效时。