Spring Batch_Intercepting Job Execution_配置JobExecutionListener
关于spring batch skip 的配置请看:http://my.oschina.net/xinxingegeya/blog/346244
在job的运行期间,我们可以捕捉job 的运行开始和结束,这些都是通过配置job 的listener 实现的。
如下配置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 包的扫描 -->
<context:component-scan base-package="com.lyx.batch" />
<bean id="exceptionHandler" class="com.lyx.batch.ExceptionListener" />
<batch:step id="abstractStep" abstract="true">
<batch:listeners>
<batch:listener ref="exceptionHandler" />
</batch:listeners>
</batch:step>
<bean id="abstractCursorReader" abstract="true"
class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- add people desc job begin -->
<batch:job id="addPeopleDescJob">
<batch:step id="addDescStep" parent="abstractStep">
<batch:tasklet>
<batch:chunk reader="peopleAddDescReader" processor="allowSkipProcessor"
writer="addDescPeopleWriter" commit-interval="2" skip-limit="10">
<batch:skippable-exception-classes>
<!--batch:include配置允许发生的异常 -->
<batch:include class="com.lyx.batch.InvalidDataException" />
</batch:skippable-exception-classes>
</batch:chunk>
</batch:tasklet>
</batch:step>
<!-- 在job的运行期间,可以监视job -->
<batch:listeners>
<batch:listener ref="sampleListener" />
</batch:listeners>
</batch:job>
<!-- add people desc job end -->
<bean id="sampleListener" class="com.lyx.batch3.SampleJobExecutionListener" />
<bean id="peopleAddDescReader" parent="abstractCursorReader"
scope="step">
<property name="sql">
<value><![CDATA[select first_name ,last_name from people where
first_name like ? or last_name like ?]]></value>
</property>
<property name="rowMapper" ref="peopleRowMapper" />
<property name="preparedStatementSetter" ref="preparedStatementSetter" />
<property name="fetchSize" value="20" />
</bean>
<bean id="peopleRowMapper" class="com.lyx.batch.PeopleRowMapper" />
<bean id="preparedStatementSetter" class="com.lyx.batch.PeoplePreparedStatementSetter" />
<bean id="allowSkipProcessor" class="com.lyx.batch.AllowSkipProcessor" />
<bean id="addDescPeopleWriter" class="com.lyx.batch.AddDescPeopleWriter" />
<!--tomcat jdbc pool数据源配置 -->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
destroy-method="close">
<property name="poolProperties">
<bean class="org.apache.tomcat.jdbc.pool.PoolProperties">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="034039" />
</bean>
</property>
</bean>
<!-- spring batch 配置jobRepository -->
<batch:job-repository id="jobRepository"
data-source="dataSource" transaction-manager="transactionManager"
isolation-level-for-create="REPEATABLE_READ" table-prefix="BATCH_"
max-varchar-length="1000" />
<!-- spring的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- batch luncher -->
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
</beans>
其中最主要的就是:
<!-- add people desc job begin -->
<batch:job id="addPeopleDescJob">
<batch:step id="addDescStep" parent="abstractStep">
<batch:tasklet>
<batch:chunk reader="peopleAddDescReader" processor="allowSkipProcessor"
writer="addDescPeopleWriter" commit-interval="2" skip-limit="10">
<batch:skippable-exception-classes>
<!--batch:include配置允许发生的异常 -->
<batch:include class="com.lyx.batch.InvalidDataException" />
</batch:skippable-exception-classes>
</batch:chunk>
</batch:tasklet>
</batch:step>
<!-- 在job的运行期间,可以监视job -->
<batch:listeners>
<batch:listener ref="sampleListener" />
</batch:listeners>
</batch:job>
<!-- add people desc job end -->
<bean id="sampleListener" class="com.lyx.batch3.SampleJobExecutionListener" />
通过实现 JobExecutionListener接口捕捉job 运行事件:
SampleJobExecutionListener.java
package com.lyx.batch3;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobExecutionListener;
public class SampleJobExecutionListener implements JobExecutionListener {
public void beforeJob(JobExecution jobExecution) {
System.out.println("job start.........");
}
public void afterJob(JobExecution jobExecution) {
if (jobExecution.getStatus() == BatchStatus.COMPLETED) {
// job success
System.out.println("job success.........");
} else if (jobExecution.getStatus() == BatchStatus.FAILED) {
// job failure
System.out.println("job failure.........");
}
}
}
需要注意的是 afterJob 方法不管job运行成功还是失败都会执行。
运行AppMain11.java
package com.lyx.batch;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* job execution listener
*
* @author Lenovo
*
*/
public class AppMain11 {
public static void main(String[] args)
throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
long startTime = System.currentTimeMillis(); // 获取开始时间
@SuppressWarnings("resource")
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:spring-batch-exception-listener.xml" });
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
Job job = (Job) context.getBean("addPeopleDescJob");
JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");
JobExecution result = launcher.run(job,
jobParametersBuilder.toJobParameters());
ExitStatus es = result.getExitStatus();
if (es.getExitCode().equals(ExitStatus.COMPLETED.getExitCode())) {
System.out.println("任务正常完成");
} else {
System.out.println("任务失败,exitCode=" + es.getExitCode());
}
long endTime = System.currentTimeMillis(); // 获取结束时间
System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
}
}
运行结果:
信息: Job: [FlowJob: [name=addPeopleDescJob]] launched with the following parameters: [{}]
job start.........
十一月 19, 2014 12:27:39 下午 org.springframework.batch.core.job.SimpleStepHandler handleStep
信息: Executing step: [addDescStep]
.............................................
job success.........
十一月 19, 2014 12:27:43 下午 org.springframework.batch.core.launch.support.SimpleJobLauncher run
信息: Job: [FlowJob: [name=addPeopleDescJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]
任务正常完成
程序运行时间: 6898ms
==================END==================