企业网站怎么做才能留住客户/百度账号管理中心
网上例子很多,只是大部分都不全,而且都是复制粘贴,不是很深入。没个流程化的东西。
一.Batch框架整体初见
从网上截图
这种分层结构有三个重要的组成部分:应用层、核心层、基础架构层。应用层包含所有的批处理作业,通过Spring框架管理程序员自定义的代码。核心层包含了Batch启动和控制所需要的核心类,如:JobLauncher、Job和step等。应用层和核心层建立在基础构架层之上,基础构架层提供共通的读(ItemReader)、写(ItemWriter)、和服务(如RetryTemplate:重试模块。可以被应用层和核心层使用)。所以使用spring-batch需引入spring-batch-core.jar
和spring-batch-infrastructure.jar(建议2.1.8.RELEASE).
二.执行流程
Batch执行流程:外部控制器调用JobLauncher启动一个Job,Job调用自己的Step去实现对数据的操作,Step处理完成后,再将处理结果一步步返回给上一层。其中Job里会配置一次批次处理数量commin-interval,read读一条传给process一条重复这2个操作直到commin-interval最大值就调用一次writer操作。然后再重复上次操作直到处理完所有的数据。当这个Step的工作完成以后,或是跳到其他Step,或是结束处理。
三.关键类介绍。
JobLauncher:接口JobLauncher只有一个子类SimpleJobLauncher.负责整个batch的启动,是入口类。使用run(Jobjob, JobParameters jobParameters)方法,该方法根据JobParameters运行job
Job:接口Job有个抽象子类AbstractJob扩展了Job功能的属性,下在有很多子类,其中SimpleJob是我们常用的子类,一个job包含若干step
Step: 接口Step有个抽象子类AbstractStep扩展了Step功能的属性,下在有很多子类,其中TaskletStep是我们常用的子类,一个Step包含一个Tasklet实例,负责具体的事件。
JobRepository:JobRepository存储job及step仓库。只有一个子类SimpleJobRepository.
而JobRepositoryFactoryBean和MapJobRepositoryFactoryBean都是JobRepository工厂类
ItemReader:提供了读取数据的能力
ItemProcessor:我们可以通过它应用业务逻辑到每一条要处理的数据
ItemWriter:提供了写数据的能力
uml:
通过2副图我们可知,jobRepository必需注入到jobLauncher,job和step里,他的作用是为上述3个类做一些过滤限制及持久化机制
四.JobRepository存储信息
JobRepository是怎么保存jobInstance,jobExecution,jobParameter等信息的呢,通过数据库或内存里Map.
查看唯一子类SimpleJobRepository源码,
我们发现jobInstanceDao有两个子类JdbcJobInstanceDao和MapJobInstanceDao。查看两个子类的getJobInstance方法。JdbcJobInstanceDao. getJobInstance().
public JobInstance getJobInstance(final String jobName,final JobParameters jobParameters) {Assert.notNull(jobName, "Job name must not be null.");Assert.notNull(jobParameters, "JobParameters must not be null.");String jobKey = createJobKey(jobParameters);ParameterizedRowMapper<JobInstance> rowMapper = new JobInstanceRowMapper(jobParameters);List<JobInstance> instances;if (StringUtils.hasLength(jobKey)) {
//通过jdbc连接数据库,执行sql语句,
//SELECT JOB_INSTANCE_ID,JOB_NAME from %PREFIX%JOB_INSTANCE where JOB_NAME = ? and //JOB_KEY = ?
instances = getJdbcTemplate().query(getQuery(FIND_JOBS_WITH_KEY),rowMapper, jobName, jobKey);} else {instances = getJdbcTemplate().query(getQuery(FIND_JOBS_WITH_EMPTY_KEY), rowMapper, jobName,jobKey);}if (instances.isEmpty()) {return null;} else {Assert.state(instances.size() == 1);return instances.get(0);}}
MapJobInstanceDao. getJobInstance:
public JobInstance getJobInstance(String jobName, JobParameters jobParameters) {
//CopyOnWriteArraySet保存jobInstance实例for (JobInstance instance : jobInstances) {if (instance.getJobName().equals(jobName) && instance.getJobParameters().equals(jobParameters)) {return instance;}}return null;}
不难发现第一个是通过数据库保存信息,第二个是集合存储。所以当我们使用第一种保存里数据库里要创建对就的表,而对应的表在Jar里有提供sql,
随便查看一下schema-mysql.sql:
-- Autogenerated: do not edit this fileCREATE TABLE BATCH_JOB_INSTANCE (JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY , VERSION BIGINT , JOB_NAME VARCHAR(100) NOT NULL, JOB_KEY VARCHAR(32) NOT NULL,constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ENGINE=InnoDB;CREATE TABLE BATCH_JOB_EXECUTION (JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,VERSION BIGINT , JOB_INSTANCE_ID BIGINT NOT NULL,CREATE_TIME DATETIME NOT NULL,START_TIME DATETIME DEFAULT NULL , END_TIME DATETIME DEFAULT NULL ,STATUS VARCHAR(10) ,EXIT_CODE VARCHAR(100) ,EXIT_MESSAGE VARCHAR(2500) ,LAST_UPDATED DATETIME,constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ENGINE=InnoDB;CREATE TABLE BATCH_JOB_PARAMS (JOB_INSTANCE_ID BIGINT NOT NULL ,TYPE_CD VARCHAR(6) NOT NULL ,KEY_NAME VARCHAR(100) NOT NULL , STRING_VAL VARCHAR(250) , DATE_VAL DATETIME DEFAULT NULL ,LONG_VAL BIGINT ,DOUBLE_VAL DOUBLE PRECISION ,constraint JOB_INST_PARAMS_FK foreign key (JOB_INSTANCE_ID)references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ENGINE=InnoDB;……………..
这也验证了数据库存储必需先创建表。而默认是使用JdbcJobInstanceDao,因为batch就是为了批操作数据库的。这点要注意,否则会报sql异常。
例子:
先看个例子的配置
<bean id="jobLauncher"class="org.springframework.batch.core.launch.support.SimpleJobLauncher"><property name="jobRepository" ref="jobRepository" /></bean><bean id="jobRepository"class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"><property name="dataSource" ref="dataSource" /><property name="transactionManager" ref="transactionManager" /></bean><bean id="taskletStep" abstract="true"class="org.springframework.batch.core.step.tasklet.TaskletStep"><property name="jobRepository" ref="jobRepository" /><property name="transactionManager" ref="transactionManager" /></bean><bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob"><property name="name" value="simpleJob" /><property name="steps"><list><bean parent="taskletStep"><property name="tasklet" ref="hello" /></bean><bean parent="taskletStep"><property name="tasklet" ref="space" /></bean><bean parent="taskletStep"><property name="tasklet" ref="world" /></bean></list></property><property name="jobRepository" ref="jobRepository" /></bean><bean id="hello" class="com.cloudeport.tasklet.TestTasklet"><property name="message" value="Hello" /></bean><bean id="space" class="com.cloudeport.tasklet.TestTasklet"><property name="message" value=" " /></bean><bean id="world" class="com.cloudeport.tasklet.TestTasklet"><property name="message" value="World!" /></bean>
TestTasklet.java:
package com.cloudeport.tasklet;import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;public class TestTasklet implements Tasklet {private String message;public void setMessage(String message) {this.message = message;}@Overridepublic RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {// TODO Auto-generated method stubSystem.out.print(message);return RepeatStatus.FINISHED;}}
启动:joblauncher.run(simpleJob,new JobParametersBuilder().toJobParameters());
Ps:要真正能启动注意数据库里创建表。
通过上的了解及UML图我们不难发现这种配置和类很匹配,直接通过属性命来配但这真是我们常用的写法吗,刚开始接触铺天盖地都这种例子,弄的很糊涂。后来直接查看官方提供的例子,发现我们常用的配置batch是通过schema配,说白点就是提供官方提供的http://www.springframework.org/schema/batch xsd文件配。
故常用的配置是:
<job id="footballJob" xmlns="http://www.springframework.org/schema/batch"><step id="playerload" next="gameLoad"><tasklet><chunk reader="playerFileItemReader" writer="playerWriter"commit-interval="${job.commit.interval}" /></tasklet></step><step id="gameLoad" next="playerSummarization"><tasklet><chunk reader="gameFileItemReader" writer="gameWriter"commit-interval="${job.commit.interval}" /></tasklet></step><step id="playerSummarization" parent="summarizationStep" /></job>
整个流程已经了然于胸。
1. 有JobLauncher,其实只有SimpleJobLauncher
2. 有JobRepository,其中只有SimpleJobRepository,不过提供了两个工厂类。JobReository需要注入到jobLauncher,job和step里
3. 配job,job下有n个step,每个step由tasklet小程序组成包括read-process-write
4. read –write其实不用自己写,process需要自己继承实现
5. 通过joblauncher.run(simpleJob, newJobParametersBuilder().toJobParameters());方式调用。
下面的会详解ItemReader.ItemProcess,itemWriter。以后再写