2、SpringBoot集成Quartz
title: 2、SpringBoot集成Quartz
date: 2018-03-22 21:33:00
tags:
- Quartz
category: - Quartz
description: SpringBoot集成Quartz
前言
有时候需要实现动态定时任务,即工程启动后,可以实现启动和关闭任务,同时也可以设置定时计划。这就需要利用到quartz
别的先不多说,先利用配置文件制作一个简单的定时器器吧
1、利用配置文件配置定时器(很少,以后还会详解)
1.1 、导入pom依赖
<?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.hlj.quartz</groupId>
<artifactId>com-hlj-quartz</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>com-hlj-quartz</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.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.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2、resource下创建配置文件quartz.properties
#scheduler实例名称。
org.quartz.scheduler.instanceName =MyScheduler
#配置线程池的容量,即表示同时最多可运行的线程数量
org.quartz.threadPool.threadCount =3
#job存储方式,RAMJobStore是使用JobStore最简单的一种方式,它也是性能最高效的,顾名思义,JobStore是把它的数据都存储在RAM中,
# 这也是它的快速和简单配置的原因;JDBCJobStore也是一种相当有名的JobStore,它通过JDBC把数据都保存到数据库中,
# 所以在配置上会比RAMJobStore复杂一些,而且不像RAMJobStore那么快,但是当我们对数据库中的表的主键创建索引时,性能上的缺点就不是很关键的了。
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
1.3、新建一个定时器任务
继承Job类,也就是工作任务类,然后重写里面的方法 execute
package com.hlj.quartz.quartz.Job;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* @Description 任务类.
* @Author HealerJean
* @Date 2018/3/22 下午4:17.
*/
public class HelloJobOne implements Job{
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("一号任务"+new Date());
}
}
1.4、service中开始调用执行这个job
解释:
1、其实配置文件中配置的,也就是我们可以在下面使用的定时器了,也就是获取实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
2、定时器有了,下一步就是获取上面的任务,也就是获取工作详情
JobDetail jobDetail = JobBuilder.newJob(HelloJobOne.class).withIdentity("job1","group1").build();
3、工作任务有了,那么下一布,就是工作的执行时间和触发规则,交给定时器
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").startNow().withSchedule(simpleScheduleBuilder).build();
// 交由Scheduler安排触发
scheduler.scheduleJob(jobDetail,trigger);
下面是service全部代码
public void haveProperties() throws SchedulerException, InterruptedException{
/*
*在 Quartz 中, scheduler 由 scheduler 工厂创建:
* DirectSchedulerFactory 或者 StdSchedulerFactory。
*第二种工厂 StdSchedulerFactory 使用较多,
*因为 DirectSchedulerFactory 使用起来不够方便,需要作许多详细的手工编码设置。
*/
// 获取Scheduler实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
System.out.println("scheduler.start");
//具体任务.
JobDetail jobDetail = JobBuilder.newJob(HelloJobOne.class).withIdentity("job1","group1").build();
//触发时间点. (每5秒执行1次.)
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").startNow().withSchedule(simpleScheduleBuilder).build();
// 交由Scheduler安排触发
scheduler.scheduleJob(jobDetail,trigger);
//睡眠20秒.
TimeUnit.SECONDS.sleep(20);
scheduler.shutdown();//关闭定时任务调度器.
System.out.println("scheduler.shutdown");
}
1.5、controler中开始调用
/**
* @Desc 有配置文件quartz.properties
* @Date 2018/3/22 下午5:40.
*/
@GetMapping("haveProperties")
public String haveProperties() throws InterruptedException, SchedulerException {
quartzService.haveProperties();
return "使用配置文件-定时器开始执行,请观察控制台";
}
1.6、浏览器中访问吧,朋友
http://localhost:8080/haveProperties
调用的时候可以看到控制台关于,配置文件 quartz.properties 中的一些信息。 而且人物执行成功
[外链图片转存失败(img-K9WyKiY3-1566552781868)(https://raw.githubusercontent.com/HealerJean123/HealerJean123.github.io/master/blogImages/WX20180322-191414.png)]
2、没有配置文件,但是很牛逼的真正的quartz
2.1、定义一个工作工厂,JobFactory
package com.hlj.quartz.quartz.config;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
/**
* @Description
* @Author HealerJean
* @Date 2018/3/22 下午3:43.
*/
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
2.2、开始从定时器工厂中,找到定时器Bean
package com.hlj.quartz.quartz.config;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
/**
* @Description
* @Author HealerJean
* @Date 2018/3/22 下午3:45.
*/
@Configuration
public class QuartzConfig {
@Autowired
private JobFactory jobFactory;
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setOverwriteExistingJobs(true);
schedulerFactoryBean.setJobFactory(jobFactory);
return schedulerFactoryBean;
}
// 创建schedule
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
2.3、这个时候,我们开始一系列的方法,对定时器进行了解
实话实说,我看的比较着急,还没有对定时器自己的一些方法进行仔细深入的了解
1、这时,我们可以看到这里用到的其实就是固定时间的定时器(可以设置为某一天的几点开始执行) ,上面的定时器是没几秒开始执行。所以二者是有区别的,具体如下
SimpleScheduleBuilder是简单调用触发器,它只能指定触发的间隔时间和执行次数;
CronScheduleBuilder是类似于Linux Cron的触发器,它通过一个称为CronExpression的规则来指定触发规则,通常是每次触发的具体时间;
CalendarIntervalScheduleBuilder是对CronScheduleBuilder的补充,它能指定每隔一段时间触发一次。
2、针对暂停,和关闭任务,也是是利用触发规则的name和group,然后判断这个规则是否存在工作,如果存在则执行定时器
3、下面我设置了两个任务。controller中对这两个任务进行观察
package com.hlj.quartz.quartz.service;
import com.hlj.quartz.quartz.Job.HelloJobOne;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**
* @Description
* @Author HealerJean
* @Date 2018/3/22 下午4:38.
*/
/**
SimpleScheduleBuilder是简单调用触发器,它只能指定触发的间隔时间和执行次数;
CronScheduleBuilder是类似于Linux Cron的触发器,它通过一个称为CronExpression的规则来指定触发规则,通常是每次触发的具体时间;(关于CronExpression,详见:官方,中文网文)
CalendarIntervalScheduleBuilder是对CronScheduleBuilder的补充,它能指定每隔一段时间触发一次。
*/
@Service
public class QuartzService {
@Autowired
private Scheduler scheduler;
public void startJob(String time,String jobName,String group,Class job){
try {
// 创建jobDetail实例,绑定Job实现类
// 指明job的名称,所在组的名称,以及绑定job类
JobDetail jobDetail = JobBuilder.newJob(job).withIdentity(jobName, group).build();//设置Job的名字和组
//corn表达式 每2秒执行一次
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time/*"0/2 * * * * ?"*/);
//设置定时任务的时间触发规则
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName,group) .withSchedule(scheduleBuilder).build();
System.out.println(scheduler.getSchedulerName());
// 把作业和触发器注册到任务调度中, 启动调度
scheduler.scheduleJob(jobDetail,cronTrigger);
/*
// 启动调度
scheduler.start();
Thread.sleep(30000);
// 停止调度
scheduler.shutdown();*/
} catch (Exception e) {
e.printStackTrace();
}
}
public void startJob2(String time,String jobName,String group,Class job){
try {
JobDetail jobDetail = JobBuilder.newJob(job).withIdentity(jobName, group).build();//设置Job的名字和组
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time/*"0/2 * * * * ?"*/);
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName,group) .withSchedule(scheduleBuilder).build();
System.out.println(scheduler.getSchedulerName());
scheduler.scheduleJob(jobDetail,cronTrigger);
} catch (Exception e) {
e.printStackTrace();
}
}
/****
* 暂停一个任务
* @param triggerName
* @param triggerGroupName
*/
public void pauseJob(String triggerName,String triggerGroupName){
try {
JobKey jobKey = new JobKey(triggerName, triggerGroupName);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail==null){
return;
}
System.out.println("开始暂停一个定时器");
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/****
* 暂停重启一个定时器任务
* @param triggerName
* @param triggerGroupName
*/
public void resumeJob(String triggerName,String triggerGroupName){
try {
JobKey jobKey = new JobKey(triggerName, triggerGroupName);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail==null){
return;
}
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/****
* 删除一个定时器任务,删除了,重启就没什么用了
* @param triggerName
* @param triggerGroupName
*/
public void deleteJob(String triggerName,String triggerGroupName){
try {
JobKey jobKey = new JobKey(triggerName, triggerGroupName);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail==null){
return;
}
scheduler.deleteJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/***
* 根据出发规则匹配任务,立即执行定时任务,暂停的时候可以用
*/
public void doJob(String triggerName,String triggerGroupName){
try {
JobKey jobKey = JobKey.jobKey(triggerName, triggerGroupName);
scheduler.triggerJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/***
* 开启定时器,这时才可以开始所有的任务,默认是开启的
*/
public void startAllJob(){
try {
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 关闭定时器,则所有任务不能执行和创建
*/
public void shutdown(){
try {
scheduler.shutdown();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
2.4、controller控制执行,注意观察控制台
package com.hlj.quartz.controller;
import com.hlj.quartz.quartz.Job.HelloJoTwo;
import com.hlj.quartz.quartz.service.QuartzService;
import com.hlj.quartz.quartz.Job.HelloJobOne;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description
* @Author HealerJean
* @Date 2018/3/22 下午4:47.
*/
@RestController
public class QuartzController {
@Autowired
private QuartzService quartzService;
@GetMapping("quartzStart")
public String startNNoQuartz(){
quartzService.startJob("0/1 * * * * ? ","job1","gropu1", HelloJobOne.class);
quartzService.startJob("0/2 * * * * ? ","job2","gropu2", HelloJoTwo.class);
return "定时器任务开始执行,请注意观察控制台";
}
@GetMapping("pauseJob")
public String pauseJob(){
quartzService.pauseJob("job1","gropu1");
return "暂停一个定时器任务,请注意观察控制台";
}
@GetMapping("resumeJob") //shutdown关闭了,或者删除了就不能重启了
public String resumeJob(){
quartzService.resumeJob("job1","gropu1");
return "暂停重启一个定时器任务,请注意观察控制台";
}
@GetMapping("deleteJob")
public String deleteJob(){
quartzService.deleteJob("job1","gropu1");
return "删除一个定时器任务,请注意观察控制台,删除了,重启就没什么用了";
}
@GetMapping("doJob")
public String doJob(){
quartzService.doJob("job1","gropu1");
return "根据出发规则匹配任务,立即执行定时任务,暂停的时候可以用";
}
@GetMapping("startAllJob")
public String startAllJob(){
quartzService.startAllJob();
return "开启定时器,这时才可以开始所有的任务,默认是开启的";
}
@GetMapping("shutdown")
public String shutdown(){
quartzService.shutdown();
return "关闭定时器,则所有任务不能执行和创建";
}
2.5、日期的匹配规则
表达式 | 允许值 |
---|---|
“0 0 12 * * ?” | 每天中午12点触发 |
“0 15 10 ? * *” | 每天上午10:15触发 |
“0 15 10 * * ?” | 每天上午10:15触发 |
“0 15 10 * * ? *” | 每天上午10:15触发 |
“0 15 10 * * ? 2005” | 2005年的每天上午10:15触发 |
“0 * 14 * * ?” | 在每天下午2点到下午2:59期间的每1分钟触发 |
“0 0/5 14 * * ?” | 在每天下午2点到下午2:55期间的每5分钟触发 |
“0 0/5 14,18 * * ?” | 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 |
“0 0-5 14 * * ?” | 在每天下午2点到下午2:05期间的每1分钟触发 |
“0 10,44 14 ? 3 WED” | 每年三月的星期三的下午2:10和2:44触发 |
“0 15 10 ? * MON-FRI” | 周一至周五的上午10:15触发 |
“0 15 10 15 * ?” | 每月15日上午10:15触发 |
“0 15 10 L * ?” | 每月最后一日的上午10:15触发 |
“0 15 10 ? * 6L” | 每月的最后一个星期五上午10:15触发 |
“0 15 10 ? * 6L 2002-2005” | 2002年至2005年的每月的最后一个星期五上午10:15触发 |
“0 15 10 ? * 6#3” | 每月的第三个星期五上午10:15触发 |
0 6 * * * | 每天早上6点 |
0 /2 * * | 每两个小时 |
0 23-7/2,8 * * * | 晚上11点到早上8点之间每两个小时,早上八点 |
0 11 4 * 1-3 | 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点 |
0 4 1 1 * | 1月1日早上4点 |
代码下载
如果满意,请打赏博主任意金额,感兴趣的请下方留言吧。可与博主自由讨论哦
支付包 | 微信 | 微信公众号 |
---|---|---|