Springboot 2.1.2 整合quartz 2.3.0
2019-01-29 本文已影响0人
Lanjerry
说明:
核心框架: SpringBoot 2.1.2
任务调度框架: Quartz 2.3.0
持久层框架: mybatis-plus 3.0.7
数据库:mysql 8.0.12
1.项目目录结构
image.png2.数据库表结构
DROP TABLE IF EXISTS `schedule_job`;
CREATE TABLE `schedule_job` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '任务id',
`job_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务名称',
`cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron表达式',
`bean_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '服务名称',
`method_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '方法名称',
`status` int(1) NOT NULL DEFAULT 1 COMMENT '状态 1.启动 2.暂停',
`delete_flag` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除 0.否 1.是',
`creator_id` int(11) NULL DEFAULT NULL COMMENT '创建人id',
`creator_name` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',
`created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`updated_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
3.pom.xml
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!--Mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!--Mybatis-Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.7</version>
</dependency>
<!--Test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.application.yml
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/lanjerry?useUnicode=yes&characterEncoding=UTF8&useSSL=false&serverTimezone=CTT&allowMultiQueries=true
username: root
password: 123456
hikari:
max-lifetime: 1765000
maximum-pool-size: 15
aop:
proxy-target-class: true
auto: true
#mybatis-plus配置
mybatis-plus:
global-config:
db-config:
field-strategy: not_empty
id-type: auto
db-type: mysql
logic-delete-value: 1
logic-not-delete-value: 0
banner: false
mapper-locations: classpath:/mapper/*Mapper.xml
type-aliases-package: com.example.demo.domain
5.Quartz配置:QuartzConfig.class
@Configuration
public class QuartzConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setOverwriteExistingJobs(true);//覆盖已存在的任务
schedulerFactoryBean.setStartupDelay(60);//延时60秒启动定时任务,避免系统未完全启动却开始执行定时任务的情况
return schedulerFactoryBean;
}
// 创建schedule
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
6.实体:ScheduleJob.class,枚举:JobOperateEnum
@TableName("schedule_job")
public class ScheduleJob implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 任务名称
*/
private String jobName;
/**
* cron表达式
*/
private String cronExpression;
/**
* 服务名称
*/
private String beanName;
/**
* 方法名称
*/
private String methodName;
/**
* 状态 1.启动 2.暂停
*/
private int status;
/**
* 是否删除 0.否 1.是
*/
@TableField(fill = FieldFill.INSERT)
@TableLogic
private Boolean deleteFlag;
/**
* 创建人id
*/
@TableField(fill = FieldFill.INSERT)
private Integer creatorId;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private String creatorName;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updatedTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public Boolean getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(Boolean deleteFlag) {
this.deleteFlag = deleteFlag;
}
public Integer getCreatorId() {
return creatorId;
}
public void setCreatorId(Integer creatorId) {
this.creatorId = creatorId;
}
public String getCreatorName() {
return creatorName;
}
public void setCreatorName(String creatorName) {
this.creatorName = creatorName;
}
public LocalDateTime getCreatedTime() {
return createdTime;
}
public void setCreatedTime(LocalDateTime createdTime) {
this.createdTime = createdTime;
}
public LocalDateTime getUpdatedTime() {
return updatedTime;
}
public void setUpdatedTime(LocalDateTime updatedTime) {
this.updatedTime = updatedTime;
}
}
public enum JobOperateEnum {
START(1, "启动"),
PAUSE(2, "暂停"),
DELETE(3, "删除");
private final Integer value;
private final String desc;
JobOperateEnum(final Integer value, final String desc) {
this.value = value;
this.desc = desc;
}
public Serializable getValue() {
return this.value;
}
// Jackson 注解为 JsonValue 返回中文 json 描述
public String getDesc() {
return this.desc;
}
public String getEnumName() {
return name();
}
}
7.任务的调度工厂(主要是实现具体的执行)QuartzFactory.class
public class QuartzFactory implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//获取调度数据
ScheduleJob scheduleJob = (ScheduleJob) jobExecutionContext.getMergedJobDataMap().get("scheduleJob");
//获取对应的Bean
Object object = SpringUtil.getBean(scheduleJob.getBeanName());
try {
//利用反射执行对应方法
Method method = object.getClass().getMethod(scheduleJob.getMethodName());
method.invoke(object);
} catch (Exception e) {
e.printStackTrace();
}
}
}
8.具体的任务调度以及触发设置:QuartzServiceImpl.class(略过接口)
@Service
@Transactional
public class QuartzServiceImpl implements QuartzService {
/**
* 调度器
*/
@Autowired
private Scheduler scheduler;
@Autowired
private ScheduleJobService jobService;
@Override
public void timingTask() {
//查询数据库是否存在需要定时的任务
List<ScheduleJob> scheduleJobs = jobService.list();
if (scheduleJobs != null) {
scheduleJobs.forEach(this::addJob);
}
}
@Override
public void addJob(ScheduleJob job) {
try {
//创建触发器
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName())
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
.startNow()
.build();
//创建任务
JobDetail jobDetail = JobBuilder.newJob(QuartzFactory.class)
.withIdentity(job.getJobName())
.build();
//传入调度的数据,在QuartzFactory中需要使用
jobDetail.getJobDataMap().put("scheduleJob", job);
//调度作业
scheduler.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void operateJob(JobOperateEnum jobOperateEnum, ScheduleJob job) throws SchedulerException {
JobKey jobKey = new JobKey(job.getJobName());
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
//抛异常
}
switch (jobOperateEnum) {
case START:
scheduler.resumeJob(jobKey);
break;
case PAUSE:
scheduler.pauseJob(jobKey);
break;
case DELETE:
scheduler.deleteJob(jobKey);
break;
}
}
@Override
public void startAllJob() throws SchedulerException {
scheduler.start();
}
@Override
public void pauseAllJob() throws SchedulerException {
scheduler.standby();
}
}
9.实现CommandLineRunner接口,以达到开机启动执行:JobSchedule.class
@Component
public class JobSchedule implements CommandLineRunner {
@Autowired
private QuartzService taskService;
/**
* 任务调度开始
* @param strings
* @throws Exception
*/
@Override
public void run(String... strings) throws Exception {
System.out.println("任务调度开始==============任务调度开始");
taskService.timingTask();
System.out.println("任务调度结束==============任务调度结束");
}
}
10.基础的配置完成,以下是几个简单的例子
执行的Job1:
@Component("testJob01")
@Transactional
public class TestJob01 {
public void execute() {
System.out.println("-------------------TestJob01任务执行开始-------------------");
System.out.println(new Date());
System.out.println("-------------------TestJob01任务执行结束-------------------");
}
}
执行的Job2:
@Component("testJob02")
@Transactional
public class TestJob02 {
public void execute() {
System.out.println("-------------------TestJob02任务执行开始-------------------");
System.out.println(new Date());
System.out.println("-------------------TestJob02任务执行结束-------------------");
}
}
配置的数据库:
image.png
11.业务类实现:ScheduleJobServiceImpl.class(略过接口)
@Service
@Transactional
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJob> implements ScheduleJobService {
@Autowired
private QuartzService quartzService;
@Override
public void add(ScheduleJob job) {
//此处省去数据验证
this.save(job);
//加入job
try {
quartzService.addJob(job);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void start(int id) {
//此处省去数据验证
ScheduleJob job = this.getById(id);
job.setStatus(1);
this.updateById(job);
//执行job
try {
quartzService.operateJob(JobOperateEnum.START, job);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void pause(int id) {
//此处省去数据验证
ScheduleJob job = this.getById(id);
job.setStatus(2);
this.updateById(job);
//执行job
try {
quartzService.operateJob(JobOperateEnum.PAUSE, job);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void delete(int id) {
//此处省去数据验证
ScheduleJob job = this.getById(id);
this.removeById(id);
//执行job
try {
quartzService.operateJob(JobOperateEnum.DELETE, job);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void startAllJob() {
//此处省去数据验证
ScheduleJob job = new ScheduleJob();
job.setStatus(1);
this.update(job, new QueryWrapper<>());
//执行job
try {
quartzService.startAllJob();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void pauseAllJob() {
//此处省去数据验证
ScheduleJob job = new ScheduleJob();
job.setStatus(2);
this.update(job, new QueryWrapper<>());
//执行job
try {
quartzService.pauseAllJob();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
12.Controller类:ScheduleJobController.class
@RestController
@RequestMapping("/job")
public class ScheduleJobController {
@Autowired
private ScheduleJobService jobService;
@GetMapping(value = "/hello")
public String helloSpringBoot() {
return "Hello quartz!";
}
@GetMapping("/add")
public String add() {
ScheduleJob job = new ScheduleJob();
job.setJobName("任务02");
job.setCronExpression("0/2 * * * * ?");
job.setBeanName("testJob02");
job.setMethodName("execute");
jobService.add(job);
return "新增定时任务成功";
}
@GetMapping("/start/{id}")
public String start(@PathVariable("id") Integer id) {
jobService.start(id);
return "启动定时任务成功";
}
@GetMapping("/pause/{id}")
public String pause(@PathVariable("id") Integer id) {
jobService.pause(id);
return "暂停定时任务成功";
}
@GetMapping("/delete/{id}")
public String delete(@PathVariable("id") Integer id) {
jobService.delete(id);
return "删除定时任务成功";
}
@GetMapping("/startAllJob")
public String startAllJob() {
jobService.startAllJob();
return "启动所有定时任务成功";
}
@GetMapping("/pauseAllJob")
public String pauseAllJob() {
jobService.pauseAllJob();
return "暂停所有定时任务成功";
}
}
使用spring自带的@Scheduled注解实现的定时任务
@Component
@EnableScheduling
public class SchedulerTask {
private int count = 0;
@Scheduled(cron = "*/1 * * * * ?")
private void process() {
System.out.println("this is scheduler task runing " + (count++));
System.out.println("当前时间:" + LocalTime.now());
}
}