整合spring boot + quartz + spring batch + mybatis
阿新 • • 發佈:2019-01-28
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任務
工程目錄為: