Spring Batch(4): Job具体解释
第四章 配置作业Job
4.1 基本配置
Job的配置有3个必须的属性。name,jobRepository,steps。一个简单的Job配置例如以下:
<job id="footballJob">
<step id="playerload" parent="s1" next="gameLoad"/>
<step id="gameLoad" parent="s2" next="playerSummarization"/>
<step id="playerSummarization" parent="s3"/>
</job>
jobRepository默认引用名称为jobRepository的bean,当然也能够显式地配置:
<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>
4.1.1 Restartable属性
该属性定义Job能否够被重新启动,默觉得true,在JobExecution运行失败后,能够创建还有一个JobExecution来继续上次的运行。
可是假设该属性设为false。又一次运行该JobInstance将抛出异常。
<job id="footballJob" restartable="false">
...
</job>
4.1.2 拦截Job运行
Spring Batch在Job的生命周期中提供了一些钩子方法,可这些钩子方法通过Listener的形式提供。JobListener的接口定义例如以下:
public interface JobExecutionListener {
void beforeJob(JobExecution jobExecution);
void afterJob(JobExecution jobExecution);
}
通过实现JobExecutionListener接口并配置给Job,能够在Job运行前后运行特定的逻辑。
比如在运行结束之后。假设失败,发送邮件通知管理人员等。
<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>
须要注意的是。不管Job是否成功运行,afterJob方法都会运行。Job是否运行成功,能够从JobExecution中获取。
public void afterJob(JobExecution jobExecution){
if( jobExecution.getStatus() == BatchStatus.COMPLETED ){
//job success
}
else if(jobExecution.getStatus() == BatchStatus.FAILED){
//job failure
}
}
Listener的运行顺序:
beforeJob与配置的顺序一样,afterJob与配置的顺序相反。
Listener异常:
Listener的运行过程中假设抛出异常,将导致Job无法继续完毕,终于状态为FAILED.因此要合理控制Listener异常对业务的影响。
注解支持:
假设不想使用侵入性强的Listener接口,能够使用@BeforeJob和@AfterJob两个注解声明。
4.1.3 Job抽象与继承
通用的Job配置能够抽取出来,作为抽象的Job存在,抽象的Job不同意被实例化:
<job id="baseJob" abstract="true">
<listeners>
<listener ref="listenerOne"/>
<listeners>
</job>
子Job能够通过继续共用这些配置(当然。也能够继承非抽象的Job)。
<job id="job1" parent="baseJob">
<step id="step1" parent="standaloneStep"/>
<listeners merge="true">
<listener ref="listenerTwo"/>
<listeners>
</job>
当中的merge=”true”表示合并父job和子job的配置,也就是两个Listener都生效。同常规的Spring配置。
4.1.4 Job參数验证
JobParameterValidator组件用于验证JobParameter。
通过以下配置为job配置验证器:
<job id="job1" parent="baseJob3">
<step id="step1" parent="standaloneStep"/>
<validator ref="paremetersValidator"/>
</job>
4.1.4 属性的Late Binding
在Spring中。能够把Bean配置用到的属性值通过PropertiesPlaceHolderConfiguer把属性从配置中分离出来独立管理,理论上来说,在配置Job的时候也能够使用同样的方式。可是Spring Batch提供了在运行时配置參数值的能力:
<bean:property name="filePath" value="#{jobParameters['filePath']}" />
在启动Job时:
launcher.executeJob("job.xml" , "footjob",
new JobParametersBuilder().addDate("day", new Date()))
.addString("filePath", "/opt/data/test.xml"));
4.2 配置JobRepository
JobRepository为任务框架中的各个组件对象提供CRUD操作,比如JobExecution,StepExecution。
一个配置样例例如以下:
<job-repository id="jobRepository"
data-source="dataSource"
transaction-manager="transactionManager"
isolation-level-for-create="SERIALIZABLE"
table-prefix="BATCH_"
max-varchar-length="1000"/>
4.2.1 事务配置
JobRepository的操作须要事务来保证其完整性以及正确性,这些元数据的完整性对框架来说非常重要。假设没有事务支持。框架的行为将无法正确定义。
create*方法的事务隔离级别单独定义,为了保证同一个JobInstance不会被同一时候运行两次,默认的隔离级别为SERIALIZABLE。能够被改动:
<job-repository id="jobRepository"
isolation-level-for-create="REPEATABLE_READ" />
假设没有使用Batch命名空间或者没有使用Factory Bean,则须要显示配置事务AOP:
<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>
4.2.2 表名前缀
默认情况下,Spring Batch须要的表以BATCH作为前缀,只是能够自己定义:
<job-repository id="jobRepository"
table-prefix="e_batch" />
表前缀能够改动,可是表名和表的列不能被改动。
4.2.3 特殊的Repository
測试环境中。内存级别的数据库十分方便:
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
</bean>
假设使用的数据库类型不在SpringBatch的支持中,能够通过JobRepositoryFactoryBean自己定义。
4.3 配置JobLauncher
默认提供了一个简单的Launcher:
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
JobLauncher的时序图例如以下:
假设启动的请求来自HTTP,那么等待整个Job完毕再返回不是一个好方法。此时须要异步启动Job,时序图例如以下:
对应的Launcher配置例如以下:
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
</property>
</bean>
4.4 运行Job
有多种方式能够启动一个Job。可是核心都是通过JobLauncher来实现。
1. 命令行运行
主要通过CommandLineJobRunner类完毕
2. 从Web容器中运行
通过Http请求启动任务非经常见。时序图例如以下:
Controller能够是常规的Spring MVC Controller:
@Controller
public class JobLauncherController {
@Autowired
JobLauncher jobLauncher;
@Autowired
Job job;
@RequestMapping("/jobLauncher.html")
public void handle() throws Exception{
jobLauncher.run(job, new JobParameters());
}
}
3. 使用调度框架运行
能够与其它调度框架一起使用,比如使用Spring的轻量级调用框架Spring Scheduler或者Quartz
4.5 元数据的高级使用方法
除了通过JobRepository对元数据进行CRUD操作外,Spring batch还提供另外的接口用于訪问元数据。
包含: JobExplorer JobOperator。
总体结构例如以下:
4.5.1 JobExplorer
该组件提供了仅仅读的查询操作,是JobRepository的仅仅读版本号,接口定义例如以下:
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 id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" />
假设须要制定表名前缀:
<bean id="jobExplorer" class="org.spr...JobExplorerFactoryBean"
p:dataSource-ref="dataSource" p:tablePrefix="BATCH_" />
4.5.2 JobOperator
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();
}
配置:
<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>
当中的startNextInstance方法将使用当前Job的JobParameter。经过JobParametersIncrementer处理之后的參数启动一个JobInstance。
public interface JobParametersIncrementer {
JobParameters getNext(JobParameters parameters);
}
以下是一个简单实现:
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();
}
}
为job配置incrementer:
<job id="footballJob" incrementer="sampleIncrementer">
...
</job>
在每天处理一次的批处理中,Incrementer的实现可能是按日期递增。
Spring Batch(4): Job具体解释的更多相关文章
- Springboot集成Spring Batch
Spring官网 (https://spring.io/projects/spring-batch#overview)对Spring Batch的解释: 一个轻量级的.全面的批处理框架,用于开发对企 ...
- spring batch批处理框架学习
内如主要来自以下链接: http://www.importnew.com/26177.html http://www.infoq.com/cn/articles/analysis-of-large-d ...
- Spring Batch 批处理框架介绍
前言 在大型的企业应用中,或多或少都会存在大量的任务需要处理,如邮件批量通知所有将要过期的会员,日终更新订单信息等.而在批量处理任务的过程中,又需要注意很多细节,如任务异常.性能瓶颈等等.那么,使用一 ...
- Spring batch学习 (1)
Spring Batch 批处理框架 埃森哲和Spring Source研发 主要解决批处理数据的问题,包含并行处理,事务处理机制等.具有健壮性 可扩展,和自带的监控功能,并且支持断点和重发.让程序员 ...
- 思维导图与Spring Batch
最近在学画图,又在复习Spring Batch.不解释,直接上图. 第三章,用XMind画的. 第五章,用iMindMap画的.
- Spring Boot整合Spring Batch
引言 Spring Batch是处理大量数据操作的一个框架,主要用来读取大量数据,然后进行一定的处理后输出指定的形式.比如我们可以将csv文件中的数据(数据量几百万甚至几千万都是没问题的)批处理插入保 ...
- Spring Batch在大型企业中的最佳实践
在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...
- spring batch资料收集
spring batch官网 Spring Batch在大型企业中的最佳实践 一篇文章全面解析大数据批处理框架Spring Batch Spring Batch系列总括
- Spring Batch学习笔记三:JobRepository
此系列博客皆为学习Spring Batch时的一些笔记: Spring Batch Job在运行时有很多元数据,这些元数据一般会被保存在内存或者数据库中,由于Spring Batch在默认配置是使用H ...
随机推荐
- C++之字符串表达式求值
关于字符串表达式求值,应该是程序猿们机试或者面试时候常见问题之一,昨天参加国内某IT的机试,压轴便为此题,今天抽空对其进行了研究. 算术表达式中最常见的表示法形式有 中缀.前缀和 后缀表示法.中缀表示 ...
- 【Luogu】P2680运输计划(树上差分+二分)
题目链接 总体思路……怎么说呢……是个暴力吧…… 首先用倍增预处理出每条路径的长度. 然后按长度把路径排序. 然后二分答案.对于当前答案mid检验,怎么检验呢? 首先差分把所有长度比mid大的链上除了 ...
- 使用腾讯互动直播 遇到的坑 'GLIBC_2.14' not found 问题解决
第一.查看系统glibc版本库 strings /lib64/libc.so.6 |grep GLIBC_ 这里我们可以看到系统中最新的版本是2.12,这里我们升级2.14. 第二.下载和安装glib ...
- MongoDB存储引擎(上)——MMAPv1
3.0版本以前,MongoDB只有一个存储引擎——MMAP,MongoDB3.0引进了一个新的存储引擎——WiredTiger,同时对原有的MMAP引擎进行改进,产生MMAPv1存储引擎,并将其设置为 ...
- HSSF生成excel文件损坏
一开始我的代码是这样的: 然后打开创建的好的excel文件出现下面的问题:,, 这里改下代码就行,其实也不用改,添加下sheet就行,就是一开始是空的,没sheet,所以可能打不开,现在至少要创建一个 ...
- Linux下文件操作命令cat(转)
语法格式: cat [-AbeEnstTuv] [--help] [--version] fileName 参数说明: -n 或 --number:由 1 开始对所有输出的行数编号. -b 或 --n ...
- 三角网格上的寻路算法Part.1—Dijkstra算法 等
http://www.cnblogs.com/chnhideyoshi/p/AStar.html
- Mysql数据库中CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP区别
如图所示,mysql数据库中,当字段类型为timestamp时,如果默认值取CURRENT_TIMESTAMP,则在insert一条记录时,end_time的值自动设置为系统当前时间,如果勾选了 ON ...
- 【内核研究】处理者_Handler
虽然MessageQueue提供了直接读/写的函数接口.但对于程序猿来说,一般不直接读/写消息队列.之前了解到,在Looper.loop()函数中.当取出消息后,会回调msg.target对象的han ...
- 使用母版页时内容页如何使用css和javascript
由于网站的主要频道页和列表页的头部和底部都是一样的,如果将每个页面放在单独的页面中,当头部和底部需要更改时维护量太大.于是想把头部和底部做成母版页,频道页和列表页的具体内容放到内容页中.这样当头和底需 ...