1.整合的意义:
在某些应用场景下要求任务必须具备高可用性和可扩展性,单台服务器不能满足业务需求,这时就需要使用Quartz实现分布式定时任务
当然分布式下Quartz并不是最好的,但是确是最简单易实现,实现快速开发。其他选择如:xxjob 、power job ...
2.依赖:
pom依赖
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-quartz
com.alibaba
fastjson
1.2.76
com.github.xiaoymin
swagger-bootstrap-ui
1.9.6
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
org.springframework.boot
spring-boot-starter-jdbc
mysql
mysql-connector-java
5.1.49
org.mariadb.jdbc
mariadb-java-client
2.7.4
runtime
com.alibaba
druid-spring-boot-starter
1.2.8
com.zaxxer
HikariCP
3.4.5
com.baomidou
mybatis-plus
3.3.0
com.baomidou
mybatis-plus-boot-starter
3.4.2
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
项目配置
# http://localhost:8080/swagger-ui.html
# http://localhost:8080/doc.html
server:
port: 8080
spring:
datasource:
driver-class-name: org.mariadb.jdbc.Driver
username: root
password: 123456
url: jdbc:mariadb://127.0.0.1:3306/quartz_db
# swagger的配置
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# 定时配置
quartz:
# 相关属性配置
properties:
org:
quartz:
# 数据源
dataSource:
globalJobDataSource:
# URL必须大写
URL: jdbc:mariadb://127.0.0.1:3306/quartz_db
driver: org.mariadb.jdbc.Driver
maxConnections: 5
username: root
password: 123456
# 必须指定数据源类型
provider: hikaricp
scheduler:
instanceName: globalScheduler
# 实例id
instanceId: AUTO
type: com.alibaba.druid.pool.DruidDataSource
jobStore:
# 数据源
dataSource: globalJobDataSource
# JobStoreTX将用于独立环境,提交和回滚都将由这个类处理
class: org.quartz.impl.jdbcjobstore.JobStoreTX
# 驱动配置
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 表前缀
tablePrefix: QRTZ_
# 失效阈值(只有配置了这个时间,超时策略根据这个时间才有效)
misfireThreshold: 100
# 集群配置
isClustered: true
# 线程池配置
threadPool:
class: org.quartz.simpl.SimpleThreadPool
# 线程数
threadCount: 10
# 优先级
threadPriority: 5
数据库文件
/*
Navicat MySQL Data Transfer
Source Server : 本地mariadb
Source Server Version : 50505
Source Host : localhost:3306
Source Database : quartz_db
Target Server Type : MYSQL
Target Server Version : 50505
File Encoding : 65001
Date: 2023-09-11 22:56:52
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for qrtz_blob_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_blob_triggers`;
CREATE TABLE `qrtz_blob_triggers` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`trigger_name` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
`trigger_group` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
`blob_data` blob DEFAULT NULL COMMENT '存放持久化Trigger对象',
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Blob类型的触发器表';
-- ----------------------------
-- Records of qrtz_blob_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for qrtz_calendars
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_calendars`;
CREATE TABLE `qrtz_calendars` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`calendar_name` varchar(200) NOT NULL COMMENT '日历名称',
`calendar` blob NOT NULL COMMENT '存放持久化calendar对象',
PRIMARY KEY (`sched_name`,`calendar_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='日历信息表';
-- ----------------------------
-- Records of qrtz_calendars
-- ----------------------------
-- ----------------------------
-- Table structure for qrtz_cron_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_cron_triggers`;
CREATE TABLE `qrtz_cron_triggers` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`trigger_name` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
`trigger_group` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
`cron_expression` varchar(200) NOT NULL COMMENT 'cron表达式',
`time_zone_id` varchar(80) DEFAULT NULL COMMENT '时区',
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Cron类型的触发器表';
-- ----------------------------
-- Records of qrtz_cron_triggers
-- ----------------------------
INSERT INTO `qrtz_cron_triggers` VALUES ('globalScheduler', '动态测试任务触发器', '触发器分组1', '0/10 * * * * ?', 'Asia/Shanghai');
-- ----------------------------
-- Table structure for qrtz_fired_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_fired_triggers`;
CREATE TABLE `qrtz_fired_triggers` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`entry_id` varchar(95) NOT NULL COMMENT '调度器实例id',
`trigger_name` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
`trigger_group` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
`instance_name` varchar(200) NOT NULL COMMENT '调度器实例名',
`fired_time` bigint(13) NOT NULL COMMENT '触发的时间',
`sched_time` bigint(13) NOT NULL COMMENT '定时器制定的时间',
`priority` int(11) NOT NULL COMMENT '优先级',
`state` varchar(16) NOT NULL COMMENT '状态',
`job_name` varchar(200) DEFAULT NULL COMMENT '任务名称',
`job_group` varchar(200) DEFAULT NULL COMMENT '任务组名',
`is_nonconcurrent` varchar(1) DEFAULT NULL COMMENT '是否并发',
`requests_recovery` varchar(1) DEFAULT NULL COMMENT '是否接受恢复执行',
PRIMARY KEY (`sched_name`,`entry_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='已触发的触发器表';
-- ----------------------------
-- Records of qrtz_fired_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for qrtz_job_details
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_job_details`;
CREATE TABLE `qrtz_job_details` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`job_name` varchar(200) NOT NULL COMMENT '任务名称',
`job_group` varchar(200) NOT NULL COMMENT '任务组名',
`description` varchar(250) DEFAULT NULL COMMENT '相关介绍',
`job_class_name` varchar(250) NOT NULL COMMENT '执行任务类名称',
`is_durable` varchar(1) NOT NULL COMMENT '是否持久化',
`is_nonconcurrent` varchar(1) NOT NULL COMMENT '是否并发',
`is_update_data` varchar(1) NOT NULL COMMENT '是否更新数据',
`requests_recovery` varchar(1) NOT NULL COMMENT '是否接受恢复执行',
`job_data` blob DEFAULT NULL COMMENT '存放持久化job对象',
PRIMARY KEY (`sched_name`,`job_name`,`job_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='任务详细信息表';
-- ----------------------------
-- Records of qrtz_job_details
-- ----------------------------
INSERT INTO `qrtz_job_details` VALUES ('globalScheduler', '动态测试任务', '任务分组1', '动态测试任务', 'com.example.job.DynamicJob', '0', '1', '1', '0', 0xACED0005737200156F72672E71756172747A2E4A6F62446174614D61709FB083E8BFA9B0CB020000787200266F72672E71756172747A2E7574696C732E537472696E674B65794469727479466C61674D61708208E8C3FBC55D280200015A0013616C6C6F77735472616E7369656E74446174617872001D6F72672E71756172747A2E7574696C732E4469727479466C61674D617013E62EAD28760ACE0200025A000564697274794C00036D617074000F4C6A6176612F7574696C2F4D61703B787001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F4000000000000C77080000001000000001740006636F6E66696774000FE5BD93E5898DE695B0636F6E6669677800);
-- ----------------------------
-- Table structure for qrtz_locks
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_locks`;
CREATE TABLE `qrtz_locks` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`lock_name` varchar(40) NOT NULL COMMENT '悲观锁名称',
PRIMARY KEY (`sched_name`,`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='存储的悲观锁信息表';
-- ----------------------------
-- Records of qrtz_locks
-- ----------------------------
INSERT INTO `qrtz_locks` VALUES ('globalScheduler', 'STATE_ACCESS');
INSERT INTO `qrtz_locks` VALUES ('globalScheduler', 'TRIGGER_ACCESS');
-- ----------------------------
-- Table structure for qrtz_paused_trigger_grps
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
CREATE TABLE `qrtz_paused_trigger_grps` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`trigger_group` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
PRIMARY KEY (`sched_name`,`trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='暂停的触发器表';
-- ----------------------------
-- Records of qrtz_paused_trigger_grps
-- ----------------------------
-- ----------------------------
-- Table structure for qrtz_scheduler_state
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_scheduler_state`;
CREATE TABLE `qrtz_scheduler_state` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`instance_name` varchar(200) NOT NULL COMMENT '实例名称',
`last_checkin_time` bigint(13) NOT NULL COMMENT '上次检查时间',
`checkin_interval` bigint(13) NOT NULL COMMENT '检查间隔时间',
PRIMARY KEY (`sched_name`,`instance_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='调度器状态表';
-- ----------------------------
-- Records of qrtz_scheduler_state
-- ----------------------------
INSERT INTO `qrtz_scheduler_state` VALUES ('globalScheduler', '小米笔记本1694095821427', '1694095953145', '7500');
-- ----------------------------
-- Table structure for qrtz_simple_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simple_triggers`;
CREATE TABLE `qrtz_simple_triggers` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`trigger_name` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
`trigger_group` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
`repeat_count` bigint(7) NOT NULL COMMENT '重复的次数统计',
`repeat_interval` bigint(12) NOT NULL COMMENT '重复的间隔时间',
`times_triggered` bigint(10) NOT NULL COMMENT '已经触发的次数',
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='简单触发器的信息表';
-- ----------------------------
-- Records of qrtz_simple_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for qrtz_simprop_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
CREATE TABLE `qrtz_simprop_triggers` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`trigger_name` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键',
`trigger_group` varchar(200) NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键',
`str_prop_1` varchar(512) DEFAULT NULL COMMENT 'String类型的trigger的第一个参数',
`str_prop_2` varchar(512) DEFAULT NULL COMMENT 'String类型的trigger的第二个参数',
`str_prop_3` varchar(512) DEFAULT NULL COMMENT 'String类型的trigger的第三个参数',
`int_prop_1` int(11) DEFAULT NULL COMMENT 'int类型的trigger的第一个参数',
`int_prop_2` int(11) DEFAULT NULL COMMENT 'int类型的trigger的第二个参数',
`long_prop_1` bigint(20) DEFAULT NULL COMMENT 'long类型的trigger的第一个参数',
`long_prop_2` bigint(20) DEFAULT NULL COMMENT 'long类型的trigger的第二个参数',
`dec_prop_1` decimal(13,4) DEFAULT NULL COMMENT 'decimal类型的trigger的第一个参数',
`dec_prop_2` decimal(13,4) DEFAULT NULL COMMENT 'decimal类型的trigger的第二个参数',
`bool_prop_1` varchar(1) DEFAULT NULL COMMENT 'Boolean类型的trigger的第一个参数',
`bool_prop_2` varchar(1) DEFAULT NULL COMMENT 'Boolean类型的trigger的第二个参数',
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='同步机制的行锁表';
-- ----------------------------
-- Records of qrtz_simprop_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for qrtz_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_triggers`;
CREATE TABLE `qrtz_triggers` (
`sched_name` varchar(120) NOT NULL COMMENT '调度名称',
`trigger_name` varchar(200) NOT NULL COMMENT '触发器的名字',
`trigger_group` varchar(200) NOT NULL COMMENT '触发器所属组的名字',
`job_name` varchar(200) NOT NULL COMMENT 'qrtz_job_details表job_name的外键',
`job_group` varchar(200) NOT NULL COMMENT 'qrtz_job_details表job_group的外键',
`description` varchar(250) DEFAULT NULL COMMENT '相关介绍',
`next_fire_time` bigint(13) DEFAULT NULL COMMENT '上一次触发时间(毫秒)',
`prev_fire_time` bigint(13) DEFAULT NULL COMMENT '下一次触发时间(默认为-1表示不触发)',
`priority` int(11) DEFAULT NULL COMMENT '优先级',
`trigger_state` varchar(16) NOT NULL COMMENT '触发器状态',
`trigger_type` varchar(8) NOT NULL COMMENT '触发器的类型',
`start_time` bigint(13) NOT NULL COMMENT '开始时间',
`end_time` bigint(13) DEFAULT NULL COMMENT '结束时间',
`calendar_name` varchar(200) DEFAULT NULL COMMENT '日程表名称',
`misfire_instr` smallint(2) DEFAULT NULL COMMENT '补偿执行的策略',
`job_data` blob DEFAULT NULL COMMENT '存放持久化job对象',
PRIMARY KEY (`sched_name`,`trigger_name`,`trigger_group`),
KEY `sched_name` (`sched_name`,`job_name`,`job_group`),
CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `job_name`, `job_group`) REFERENCES `qrtz_job_details` (`sched_name`, `job_name`, `job_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='触发器详细信息表';
-- ----------------------------
-- Records of qrtz_triggers
-- ----------------------------
INSERT INTO `qrtz_triggers` VALUES ('globalScheduler', '动态测试任务触发器', '触发器分组1', '动态测试任务', '任务分组1', null, '1694095960000', '1694095950000', '5', 'WAITING', 'CRON', '1694095852000', '0', null, '2', '');
3.控制层
package com.example.controller;
import com.example.entity.JobInfo;
import com.example.service.JobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@RestController
@RequestMapping("/job")
@Api(value = "计划任务管理", tags = {"计划任务管理"})
public class JobController {
@Resource
private JobService jobService;
@Resource
private Scheduler scheduler;
@ApiOperation("查询所有的任务")
@GetMapping("/all")
public List list() throws SchedulerException {
List jobInfos = new ArrayList<>();
List triggerGroupNames = scheduler.getTriggerGroupNames();
for (String triggerGroupName : triggerGroupNames) {
Set triggerKeySet = scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));
for (TriggerKey triggerKey : triggerKeySet) {
Trigger trigger = scheduler.getTrigger(triggerKey);
JobKey jobKey = trigger.getJobKey();
JobInfo jobInfo = jobService.getJobInfo(jobKey.getGroup(), jobKey.getName());
jobInfos.add(jobInfo);
}
}
return jobInfos;
}
@ApiOperation("添加任务")
@PostMapping("/add")
public JobInfo addJob(@RequestBody JobInfo jobInfo) throws SchedulerException, ClassNotFoundException {
jobService.addJob(jobInfo);
return jobInfo;
}
@ApiOperation("暂停任务")
@PostMapping("/pause")
public void pauseJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName) throws SchedulerException {
jobService.pauseJob(jobGroup, jobName);
}
@ApiOperation("继续任务")
@PostMapping("/continue")
public void continueJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName) throws SchedulerException {
jobService.continueJob(jobGroup, jobName);
}
@ApiOperation("删除任务")
@PostMapping("/delete")
public boolean deleteJob(@RequestParam("jobGroup") String jobGroup, @RequestParam("jobName") String jobName) throws SchedulerException {
return jobService.deleteJob(jobGroup, jobName);
}
}
4.业务逻辑层:
package com.example.service;
import com.alibaba.fastjson.JSONObject;
import com.example.entity.JobInfo;
import org.quartz.*;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
@Service
public class JobService {
@Resource
private Scheduler scheduler;
/**
* 添加任务
*/
@SuppressWarnings("unchecked")
public void addJob(JobInfo jobInfo) throws SchedulerException, ClassNotFoundException {
Objects.requireNonNull(jobInfo, "任务信息不能为空");
// 生成job key
JobKey jobKey = JobKey.jobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
// 当前任务不存在才进行添加
if (!scheduler.checkExists(jobKey)) {
Class jobClass = (Class)Class.forName(jobInfo.getClassName());
// 任务明细
JobDetail jobDetail = JobBuilder
.newJob(jobClass)
.withIdentity(jobKey)
.withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup())
.withDescription(jobInfo.getJobName())
.build();
// 配置信息
jobDetail.getJobDataMap().put("config", jobInfo.getConfig());
// 定义触发器
TriggerKey triggerKey = TriggerKey.triggerKey(jobInfo.getTriggerName(), jobInfo.getTriggerGroup());
// 设置任务的错过机制
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCron()).withMisfireHandlingInstructionDoNothing())
.build();
scheduler.scheduleJob(jobDetail, trigger);
} else {
throw new SchedulerException(jobInfo.getJobName() + "任务已存在,无需重复添加");
}
}
/**
* 删除任务
*/
public boolean deleteJob(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (scheduler.checkExists(jobKey)) {
return scheduler.deleteJob(jobKey);
}
return false;
}
/**
* 任务暂停
*/
public void pauseJob(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (scheduler.checkExists(jobKey)) {
scheduler.pauseJob(jobKey);
}
}
/**
* 继续任务
*/
public void continueJob(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (scheduler.checkExists(jobKey)) {
scheduler.resumeJob(jobKey);
}
}
/**
* 获取任务信息
*/
public JobInfo getJobInfo(String jobGroup, String jobName) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
if (!scheduler.checkExists(jobKey)) {
return null;
}
List extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
if (Objects.isNull(triggers)) {
throw new SchedulerException("未获取到触发器信息");
}
TriggerKey triggerKey = triggers.get(0).getKey();
Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
JobInfo jobInfo = new JobInfo();
jobInfo.setJobName(jobGroup);
jobInfo.setJobGroup(jobName);
jobInfo.setTriggerName(triggerKey.getName());
jobInfo.setTriggerGroup(triggerKey.getGroup());
jobInfo.setClassName(jobDetail.getJobClass().getName());
jobInfo.setStatus(triggerState.toString());
if (Objects.nonNull(jobDetail.getJobDataMap())) {
jobInfo.setConfig(JSONObject.toJSONString(jobDetail.getJobDataMap()));
}
CronTrigger theTrigger = (CronTrigger) triggers.get(0);
jobInfo.setCron(theTrigger.getCronExpression());
return jobInfo;
}
}
5.job业务实现类:
package com.example.job;
import org.quartz.*;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @DisallowConcurrentExecution:这个注解的作用就是同一个任务必须在上一次执行完毕之后,再按照corn时间执行,不会并行执行
* @PersistJobDataAfterExecution:这个注解的作用就是下一个任务用到上一个任务的修改数据(定时任务里面的jobData数据流转)
*/
@Component
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
public class DynamicJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("TimeEventJob正在执行..." + LocalDateTime.now());
JobDetail jobDetail = context.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
Object orDefault = jobDataMap.getOrDefault("config", "无参数");
System.out.println(orDefault);
System.out.println("TimeEventJob执行完毕..." + LocalDateTime.now());
}
}
6.job实体类:
package com.example.entity;
import lombok.Data;
@Data
public class JobInfo {
/**
* 任务名称
*/
private String jobName;
/**
* 任务组
*/
private String jobGroup;
/**
* 触发器名称
*/
private String triggerName;
/**
* 触发器组
*/
private String triggerGroup;
/**
* cron表达式
*/
private String cron;
/**
* 类名
*/
private String className;
/**
* 状态
*/
private String status;
/**
* 下一次执行时间
*/
private String nextTime;
/**
* 上一次执行时间
*/
private String prevTime;
/**
* 配置信息(data)
*/
private String config;
}
7. swagger
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* swagger2
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller")).paths(PathSelectors.any())
.build()
/*.globalOperationParameters(setHeaderToken())*/;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("action-swagger").description("swagger实战").termsOfServiceUrl("")
.version("1.0").build();
}
/**
* 设置swagger文档中全局参数 2020/9/11 10:15
*
* @return java.util.List
*/
private List setHeaderToken() {
List pars = new ArrayList<>();
ParameterBuilder userId = new ParameterBuilder();
userId.name("token").description("用户TOKEN").modelRef(new ModelRef("string")).parameterType("header")
.required(true).build();
pars.add(userId.build());
return pars;
}
}
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author PC
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* swagger的注册配置
*
* @param registry 注册中心
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
}
/**
* 统一注册配置
* @param registry 注册中心
*/
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// ResponseFormatJsonInterceptor interceptor = new ResponseFormatJsonInterceptor();
// registry.addInterceptor(interceptor);
// }
}