quartz负责定时,spring batch负责批量,mybatis负责持久化数据库,具体每个框架的介绍请参考其它文章,本节主要做spring boot + quartz + spring batch + mybatis的整合。
案例:指定距当前时间5s后,每隔3s时间执行一次批处理任务,批处理任务是读取数据库表记录并打印出来。
数据库采用DB2数据库,库表为users,记录为:
一、建立一个spring boot工程,并在pom.xml中引入依赖jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lzj</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId>
<scope>runtime</scope> </dependency> -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、配置定时
spring-context-support的jar包作了quartz和spring batch的整合。QuartzJobBean类起连接quartz和spring batch的作用。quartz定时执行QuartzJobBean的继承类,在继承类中去执行启动批量任务,达到定时启动批量的作用。
1、创建QuartzJobBean的继承类
package com.lzj.quartz;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.h2.util.New;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.configuration.JobLocator;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class QuartzJobLauncher extends QuartzJobBean {
/*-------------方式一:获取jobName、jobLauncher和jobLocator*/
// private String jobName;
// private JobLauncher jobLauncher;
// private JobLocator jobLocator;
//
// public String getJobName() {
// return jobName;
// }
//
// public void setJobName(String jobName) {
// this.jobName = jobName;
// }
//
// public JobLauncher getJobLauncher() {
// return jobLauncher;
// }
//
// public void setJobLauncher(JobLauncher jobLauncher) {
// this.jobLauncher = jobLauncher;
// }
//
// public JobLocator getJobLocator() {
// return jobLocator;
// }
//
// public void setJobLocator(JobLocator jobLocator) {
// this.jobLocator = jobLocator;
// }
/*------------------------方式一获取结束------------------------------*/
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
/*-------------方式二:获取jobName、jobLauncher和jobLocator-------------------*/
JobDetail jobDetail = context.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
String jobName = jobDataMap.getString("jobName");
JobLauncher jobLauncher = (JobLauncher) jobDataMap.get("jobLauncher");
JobLocator jobLocator = (JobLocator) jobDataMap.get("jobLocator");
System.out.println("jobName : " + jobName);
System.out.println("jobLauncher : " + jobLauncher);
System.out.println("jobLocator : " + jobLocator);
/*-----------------------------方式二获取结束---------------------------------*/
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sf.format(new Date());
System.out.println("Current Time : " + date);
try {
Job job = jobLocator.getJob(jobName);
/*启动spring batch的批处理作业*/
JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder().addDate("date", new Date()).toJobParameters());
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、配置定时任务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="quartzJob" class="com.lzj.quartz.QuartzJobLauncher"></bean>
<!-- 注册job -->
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry"></bean>
<bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"></property>
</bean>
<!-- jobLauncher在batch-config.xml文件中定义了 -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.lzj.quartz.QuartzJobLauncher"></property>
<property name="jobDataMap">
<map>
<entry key="jobName" value="myJob"></entry>
<entry key="jobLauncher" value-ref="jobLauncher"></entry>
<entry key="jobLocator" value-ref="jobRegistry"></entry>
</map>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail"></property>
<property name="cronExpression" value="0/3 * * * * ?"></property>
<property name="startDelay" value="3000"></property>
</bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers" ref="cronTrigger"></property>
</bean>
</beans>
三、配置spring batch的job作业
1、首先创建batch的作业类,实现Tasklet接口即可
程序中用到的UserDao 与数据库打交道的接口在后面通过mybatis进行定义。
package com.lzj.springbatch.tasklet;
import java.util.List;
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 com.lzj.mybatis.dao.UserDao;
import com.lzj.springbatch.model.User;
public class MyTasklet implements Tasklet {
/*在配置文件batch-confi.xml中定义MyTasklet的bean时,传入UserDao 的属性*/
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
User user = new User();
user.setId(1);
List<User> users = userDao.select(user);
for(User user1 : users){
System.out.println(user1);
}
return RepeatStatus.FINISHED;
}
}
2、配置job作业
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- <context:property-placeholder location="classpath:db.properties"/> -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"></property>
</bean>
<batch:job id="myJob" restartable="true">
<batch:step id="myStep" allow-start-if-complete="true">
<batch:tasklet ref="myTasklet">
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="myTasklet" class="com.lzj.springbatch.tasklet.MyTasklet">
<!-- <property name="dataSource" ref="dataSource"></property> -->
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
四、配置mybatis的持久化层
1、在spring boot中整合mybatis的配置
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<bean id="propertyConfigure"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
</list>
</property>
</bean>
<!--spring batch和mybatis共用一个数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.jdbcUrl}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driverClass}" />
<property name="initialSize" value="3" />
<property name="minIdle" value="3" />
<property name="maxActive" value="3" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
</bean>
<!-- 申明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!--mybatis-config.xml为mybatis的一些属性配置,如无必须要求,可不配置-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- <property name="typeAliasesPackage" value="domain.bean" /> -->
<property name="mapperLocations">
<array>
<value>classpath:mapper/*.xml</value>
</array>
</property>
</bean>
<!-- 配置加载Dao -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lzj.mybatis.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
</beans>
mybatis-config.xml中只配置了开启mybatis的二级缓存功能
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true" />
</settings>
</configuration>
数据库的properties文件db.properties为:
jdbc.user=my_name
jdbc.password=my_password
jdbc.driverClass=com.ibm.db2.jcc.DB2Driver
jdbc.jdbcUrl=jdbc:db2:xx.xxx.xx.xxx:50000/database_name
2、创建mybatis的接口,程序通过接口来操作mybatis与数据库交互
package com.lzj.mybatis.dao;
import java.util.List;
import com.lzj.springbatch.model.User;
public interface UserDao {
public List<User> select(User user);
}
3、编写mybatis的mapper文件,接口操作mapper文件,
mapper文件与数据库交互
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzj.mybatis.dao.UserDao">
<resultMap type="com.lzj.springbatch.model.User" id="ResultMap">
<result column="ID" property="id"/>
<result column="NAME" property="name"/>
<result column="AGE" property="age"/>
</resultMap>
<select id="select" resultMap="ResultMap">
select * from SQLJ.users
<where>
<if test="id != null">ID > #{id}</if>
</where>
</select>
</mapper>
五、run
测试方法如下:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException {
Set<Object> set = new HashSet<>();
set.add("classpath:batch-config.xml");
set.add("classpath:quartz-config.xml");
set.add("applicationContext.xml");
SpringApplication app = new SpringApplication(DemoApplication.class);
app.setSources(set);
ApplicationContext context = app.run(args);
}
}
启动测试方法,输出日志如下:
……
jobName : myJob
jobLauncher : org.springframework.batch.core.launch.support.SimpleJobLauncher@4ba309ec
jobLocator : org.springframework.batch.core.configuration.support.MapJobRegistry@4564eee8
Current Time : 2018-04-13 19:48:00
2018-04-13 19:48:00.032 INFO 4788 --- [eduler_Worker-2] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=myJob]] launched with the following parameters: [{date=1523620080009}]
2018-04-13 19:48:00.090 INFO 4788 --- [eduler_Worker-2] o.s.batch.core.job.SimpleStepHandler : Executing step: [myStep]
User [id=2, name=huwei, age=28]
User [id=3, name=lijie, age=26]
2018-04-13 19:48:00.140 INFO 4788 --- [eduler_Worker-2] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=myJob]] completed with the following parameters: [{date=1523620080009}] and the following status: [COMPLETED]
jobName : myJob
jobLauncher : org.springframework.batch.core.launch.support.SimpleJobLauncher@4ba309ec
jobLocator : org.springframework.batch.core.configuration.support.MapJobRegistry@4564eee8
Current Time : 2018-04-13 19:48:03
2018-04-13 19:48:03.017 INFO 4788 --- [eduler_Worker-3] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=myJob]] launched with the following parameters: [{date=1523620083000}]
2018-04-13 19:48:03.057 INFO 4788 --- [eduler_Worker-3] o.s.batch.core.job.SimpleStepHandler : Executing step: [myStep]
User [id=2, name=huwei, age=28]
User [id=3, name=lijie, age=26]
2018-04-13 19:48:03.089 INFO 4788 --- [eduler_Worker-3] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=myJob]] completed with the following parameters: [{date=1523620083000}] and the following status: [COMPLETED]
jobName : myJob
jobLauncher : org.springframework.batch.core.launch.support.SimpleJobLauncher@4ba309ec
jobLocator : org.springframework.batch.core.configuration.support.MapJobRegistry@4564eee8
Current Time : 2018-04-13 19:48:06
2018-04-13 19:48:06.019 INFO 4788 --- [eduler_Worker-4] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=myJob]] launched with the following parameters: [{date=1523620086001}]
2018-04-13 19:48:06.058 INFO 4788 --- [eduler_Worker-4] o.s.batch.core.job.SimpleStepHandler : Executing step: [myStep]
User [id=2, name=huwei, age=28]
User [id=3, name=lijie, age=26]
2018-04-13 19:48:06.094 INFO 4788 --- [eduler_Worker-4] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=myJob]] completed with the following parameters: [{date=1523620086001}] and the following status: [COMPLETED]
……
通过日志可以看出,每3s执行一次job任务
工程目录为:
源码下载位置: https://github.com/shuniversity/-springboot-quartz-springbatch-mybatis