Spring Batch提供了Job的执行能力,其本身不是一个定时的调度框架,因此可以将定时调度框架和Spring Batch结合起来完成定时任务。Spring本身提供了一个轻量级的调度框架Spring scheduler。
Spring scheduler使用非常简单,只需要完成2步即可完成简单的定时调度功能:
(1)定义一个scheduler,给scheduler提供执行定时任务的线程。
(2)定义需要定时操作的方法和调度周期。
一、项目结构
二、代码实现
Demo9BatchMain.java:
package com.xj.demo9;
import org.springframework.batch.core.JobParameters;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author : xjfu
* @Date : 2021/11/18 8:37
* @Description :Job与定时任务集成
*/
public class Demo9BatchMain {
public static void main(String[] args) {
Demo9BatchMain batchMain = new Demo9BatchMain();
batchMain.executeJob("demo9/job/job-spring-scheduler.xml", "schedulerLauncher", "helloWorldJob", new JobParameters());
}
public void executeJob(String jobXmlPath, String jobLauncherId, String jobId, JobParameters jobParameters){
//获取Job的配置文件
ApplicationContext context = new ClassPathXmlApplicationContext(jobXmlPath);
//获取JobLauncher
SchedulerLauncher schedulerLauncher = (SchedulerLauncher) context.getBean(jobLauncherId);
try {
schedulerLauncher.launcher();
}catch (Exception e){
e.printStackTrace();
}
}
}
HelloWorldTasklet.java:
package com.xj.demo9;
import org.springframework.batch.core.JobParameter;
import org.springframework.batch.core.JobParameters;
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;
import java.util.Map;
public class HelloWorldTasklet implements Tasklet {
/* (non-Javadoc)
* @see org.springframework.batch.core.step.tasklet.Tasklet#execute(org.springframework.batch.core.StepContribution, org.springframework.batch.core.scope.context.ChunkContext)
*/
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception {
String jobName = chunkContext.getStepContext().getJobName();
System.out.println("Execute job :" + jobName +".");
JobParameters jobParameters = chunkContext.getStepContext().getStepExecution().getJobParameters();
System.out.println("JobParameters:" + jobParameterToString(jobParameters));
return RepeatStatus.FINISHED;
}
/**
* 转换为String类型格式.<br>
* @param jobParameters
* @return
*/
private String jobParameterToString(JobParameters jobParameters){
StringBuffer sb = new StringBuffer();
for(Map.Entry<String, JobParameter> param : jobParameters.getParameters().entrySet()) {
sb.append(String.format(
"%s = %s (%s);",
param.getKey(),param.getValue().getValue(),param.getValue().getType()
));
}
return sb.toString();
}
}
SchedulerLauncher.java:
package com.xj.demo9;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import java.util.Date;
/**
* @Author : xjfu
* @Date : 2021/11/30 8:23
* @Description :Spring scheduler定时调度Spring Batch中的Job
*/
public class SchedulerLauncher {
private Job job;
private JobLauncher jobLauncher;
public void launcher() throws Exception {
JobParameters jobParams = createJobParameters();
jobLauncher.run(job, jobParams);
}
private JobParameters createJobParameters(){
JobParameters jobParameters = new JobParametersBuilder()
.addDate("executeDate", new Date())
.toJobParameters();
return jobParameters;
}
public Job getJob() {
return job;
}
public void setJob(Job job) {
this.job = job;
}
public JobLauncher getJobLauncher() {
return jobLauncher;
}
public void setJobLauncher(JobLauncher jobLauncher) {
this.jobLauncher = jobLauncher;
}
}
demo9-jobContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<!--作业仓库-->
<batch:job-repository
id="jobRepository"
data-source="dataSource"
transaction-manager="transactionManager"
isolation-level-for-create="SERIALIZABLE"
table-prefix="BATCH_"
max-varchar-length="1000"/>
<!--作业调度器-->
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://127.0.0.1:3306/spring_batch_demo2</value>
</property>
<property name="username" value="root"/>
<property name="password" value="12345"/>
</bean>
</beans>
job-spring-scheduler.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
xmlns:batch="http://www.springframework.org/schema/batch"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd">
<import resource="classpath:demo9/job/demo9-jobContext.xml"/>
<!--定义执行任务时的线程池-->
<task:scheduler id="scheduler" pool-size="10"/>
<task:scheduled-tasks scheduler="scheduler">
<!--每1秒调用一次-->
<task:scheduled ref="schedulerLauncher" method="launcher" fixed-rate="1000"/>
</task:scheduled-tasks>
<bean id="schedulerLauncher" class="com.xj.demo9.SchedulerLauncher">
<property name="job" ref="helloWorldJob"/>
<property name="jobLauncher" ref="jobLauncher"/>
</bean>
<batch:job id="helloWorldJob">
<batch:step id="helloWorldStep">
<batch:tasklet>
<bean class="com.xj.demo9.HelloWorldTasklet"/>
</batch:tasklet>
</batch:step>
</batch:job>
</beans>
三、运行实现
四、未解决的问题
不知道为什么启动的时候,有时会报错,但是后面的程序还会照样正常运行,这个问题目前没有想到解决方法,留在这里,待以后解决:
报错完整内容:
org.springframework.dao.DataAccessResourceFailureException: Could not increment ID for BATCH_JOB_SEQ sequence table; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction