Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目。
Quartz是一个完全由Java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制。
Quartz可以与J2EE与J2SE应用程序相结合也可以单独使用。
Quartz允许程序开发人员根据时间的间隔来调度作业。
Quartz实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。
Quartz官网:http://www.quartz-scheduler.org/
Job
Job表示一个工作,要执行的具体内容。
JobDetail
JobDetail表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail还包含了这个任务调度的方案和策略。
Trigger
Trigger代表一个调度参数的配置,什么时候去调。
Scheduler
Scheduler代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。
Quartz采用持久化到数据库方式,需要创建官网提供的11张表。因此,可以在官网下载对应的版本,根据路径src\org\quartz\impl\jdbcjobstore
找到对应数据库类型的脚本,例如Mysql为:tables_mysql.sql
。
Mysql相关的表及系统需要的表脚本如下,请先创建数据库:quartzdemo
,并初始化数据库表结构及数据。
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_qrtz_blob_triggers
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_blob_triggers`;
CREATE TABLE `t_qrtz_blob_triggers` (
`sched_name` varchar(120) NOT NULL,
`trigger_name` varchar(190) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
`blob_data` blob NULL,
PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
INDEX `sched_name`(`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
CONSTRAINT `t_qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `t_qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
);
-- ----------------------------
-- Records of t_qrtz_blob_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_calendars
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_calendars`;
CREATE TABLE `t_qrtz_calendars` (
`sched_name` varchar(120) NOT NULL,
`calendar_name` varchar(190) NOT NULL,
`calendar` blob NOT NULL,
PRIMARY KEY (`sched_name`, `calendar_name`) USING BTREE
);
-- ----------------------------
-- Records of t_qrtz_calendars
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_cron_triggers
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_cron_triggers`;
CREATE TABLE `t_qrtz_cron_triggers` (
`sched_name` varchar(120) NOT NULL,
`trigger_name` varchar(190) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
`cron_expression` varchar(120) NOT NULL,
`time_zone_id` varchar(80) NULL DEFAULT NULL,
PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
CONSTRAINT `t_qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `t_qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
);
-- ----------------------------
-- Records of t_qrtz_cron_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_fired_triggers
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_fired_triggers`;
CREATE TABLE `t_qrtz_fired_triggers` (
`sched_name` varchar(120) NOT NULL,
`entry_id` varchar(95) NOT NULL,
`trigger_name` varchar(190) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
`instance_name` varchar(190) NOT NULL,
`fired_time` bigint(0) NOT NULL,
`sched_time` bigint(0) NOT NULL,
`priority` int(0) NOT NULL,
`state` varchar(16) NOT NULL,
`job_name` varchar(190) NULL DEFAULT NULL,
`job_group` varchar(190) NULL DEFAULT NULL,
`is_nonconcurrent` varchar(1) NULL DEFAULT NULL,
`requests_recovery` varchar(1) NULL DEFAULT NULL,
PRIMARY KEY (`sched_name`, `entry_id`) USING BTREE,
INDEX `idx_qrtz_ft_trig_inst_name`(`sched_name`, `instance_name`) USING BTREE,
INDEX `idx_qrtz_ft_inst_job_req_rcvry`(`sched_name`, `instance_name`, `requests_recovery`) USING BTREE,
INDEX `idx_qrtz_ft_j_g`(`sched_name`, `job_name`, `job_group`) USING BTREE,
INDEX `idx_qrtz_ft_jg`(`sched_name`, `job_group`) USING BTREE,
INDEX `idx_qrtz_ft_t_g`(`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
INDEX `idx_qrtz_ft_tg`(`sched_name`, `trigger_group`) USING BTREE
);
-- ----------------------------
-- Records of t_qrtz_fired_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_job_details
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_job_details`;
CREATE TABLE `t_qrtz_job_details` (
`sched_name` varchar(120) NOT NULL,
`job_name` varchar(190) NOT NULL,
`job_group` varchar(190) NOT NULL,
`description` varchar(250) NULL DEFAULT NULL,
`job_class_name` varchar(250) NOT NULL,
`is_durable` varchar(1) NOT NULL,
`is_nonconcurrent` varchar(1) NOT NULL,
`is_update_data` varchar(1) NOT NULL,
`requests_recovery` varchar(1) NOT NULL,
`job_data` blob NULL,
PRIMARY KEY (`sched_name`, `job_name`, `job_group`) USING BTREE,
INDEX `idx_qrtz_j_req_recovery`(`sched_name`, `requests_recovery`) USING BTREE,
INDEX `idx_qrtz_j_grp`(`sched_name`, `job_group`) USING BTREE
);
-- ----------------------------
-- Records of t_qrtz_job_details
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_locks
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_locks`;
CREATE TABLE `t_qrtz_locks` (
`sched_name` varchar(120) NOT NULL,
`lock_name` varchar(40) NOT NULL,
PRIMARY KEY (`sched_name`, `lock_name`) USING BTREE
);
-- ----------------------------
-- Records of t_qrtz_locks
-- ----------------------------
INSERT INTO `t_qrtz_locks` VALUES ('clusteredScheduler', 'STATE_ACCESS');
INSERT INTO `t_qrtz_locks` VALUES ('clusteredScheduler', 'TRIGGER_ACCESS');
-- ----------------------------
-- Table structure for t_qrtz_paused_trigger_grps
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_paused_trigger_grps`;
CREATE TABLE `t_qrtz_paused_trigger_grps` (
`sched_name` varchar(120) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
PRIMARY KEY (`sched_name`, `trigger_group`) USING BTREE
);
-- ----------------------------
-- Records of t_qrtz_paused_trigger_grps
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_scheduler_state
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_scheduler_state`;
CREATE TABLE `t_qrtz_scheduler_state` (
`sched_name` varchar(120) NOT NULL,
`instance_name` varchar(190) NOT NULL,
`last_checkin_time` bigint(0) NOT NULL,
`checkin_interval` bigint(0) NOT NULL,
PRIMARY KEY (`sched_name`, `instance_name`) USING BTREE
);
-- ----------------------------
-- Records of t_qrtz_scheduler_state
-- ----------------------------
INSERT INTO `t_qrtz_scheduler_state` VALUES ('clusteredScheduler', 'C3Stones-PC', 1600918524362, 10000);
-- ----------------------------
-- Table structure for t_qrtz_simple_triggers
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_simple_triggers`;
CREATE TABLE `t_qrtz_simple_triggers` (
`sched_name` varchar(120) NOT NULL,
`trigger_name` varchar(190) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
`repeat_count` bigint(0) NOT NULL,
`repeat_interval` bigint(0) NOT NULL,
`times_triggered` bigint(0) NOT NULL,
PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
CONSTRAINT `t_qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `t_qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
);
-- ----------------------------
-- Records of t_qrtz_simple_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_simprop_triggers
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_simprop_triggers`;
CREATE TABLE `t_qrtz_simprop_triggers` (
`sched_name` varchar(120) NOT NULL,
`trigger_name` varchar(190) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
`str_prop_1` varchar(512) NULL DEFAULT NULL,
`str_prop_2` varchar(512) NULL DEFAULT NULL,
`str_prop_3` varchar(512) NULL DEFAULT NULL,
`int_prop_1` int(0) NULL DEFAULT NULL,
`int_prop_2` int(0) NULL DEFAULT NULL,
`long_prop_1` bigint(0) NULL DEFAULT NULL,
`long_prop_2` bigint(0) NULL DEFAULT NULL,
`dec_prop_1` decimal(13, 4) NULL DEFAULT NULL,
`dec_prop_2` decimal(13, 4) NULL DEFAULT NULL,
`bool_prop_1` varchar(1) NULL DEFAULT NULL,
`bool_prop_2` varchar(1) NULL DEFAULT NULL,
PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
CONSTRAINT `t_qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `t_qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
);
-- ----------------------------
-- Records of t_qrtz_simprop_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for t_qrtz_triggers
-- ----------------------------
DROP TABLE IF EXISTS `t_qrtz_triggers`;
CREATE TABLE `t_qrtz_triggers` (
`sched_name` varchar(120) NOT NULL,
`trigger_name` varchar(190) NOT NULL,
`trigger_group` varchar(190) NOT NULL,
`job_name` varchar(190) NOT NULL,
`job_group` varchar(190) NOT NULL,
`description` varchar(250) NULL DEFAULT NULL,
`next_fire_time` bigint(0) NULL DEFAULT NULL,
`prev_fire_time` bigint(0) NULL DEFAULT NULL,
`priority` int(0) NULL DEFAULT NULL,
`trigger_state` varchar(16) NOT NULL,
`trigger_type` varchar(8) NOT NULL,
`start_time` bigint(0) NOT NULL,
`end_time` bigint(0) NULL DEFAULT NULL,
`calendar_name` varchar(190) NULL DEFAULT NULL,
`misfire_instr` smallint(0) NULL DEFAULT NULL,
`job_data` blob NULL,
PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE,
INDEX `idx_qrtz_t_j`(`sched_name`, `job_name`, `job_group`) USING BTREE,
INDEX `idx_qrtz_t_jg`(`sched_name`, `job_group`) USING BTREE,
INDEX `idx_qrtz_t_c`(`sched_name`, `calendar_name`) USING BTREE,
INDEX `idx_qrtz_t_g`(`sched_name`, `trigger_group`) USING BTREE,
INDEX `idx_qrtz_t_state`(`sched_name`, `trigger_state`) USING BTREE,
INDEX `idx_qrtz_t_n_state`(`sched_name`, `trigger_name`, `trigger_group`, `trigger_state`) USING BTREE,
INDEX `idx_qrtz_t_n_g_state`(`sched_name`, `trigger_group`, `trigger_state`) USING BTREE,
INDEX `idx_qrtz_t_next_fire_time`(`sched_name`, `next_fire_time`) USING BTREE,
INDEX `idx_qrtz_t_nft_st`(`sched_name`, `trigger_state`, `next_fire_time`) USING BTREE,
INDEX `idx_qrtz_t_nft_misfire`(`sched_name`, `misfire_instr`, `next_fire_time`) USING BTREE,
INDEX `idx_qrtz_t_nft_st_misfire`(`sched_name`, `misfire_instr`, `next_fire_time`, `trigger_state`) USING BTREE,
INDEX `idx_qrtz_t_nft_st_misfire_grp`(`sched_name`, `misfire_instr`, `next_fire_time`, `trigger_group`, `trigger_state`) USING BTREE,
CONSTRAINT `t_qrtz_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `job_name`, `job_group`) REFERENCES `t_qrtz_job_details` (`sched_name`, `job_name`, `job_group`) ON DELETE RESTRICT ON UPDATE RESTRICT
);
-- ----------------------------
-- Records of t_qrtz_triggers
-- ----------------------------
-- ----------------------------
-- Table structure for t_sys_job
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_job`;
CREATE TABLE `t_sys_job` (
`id` int(0) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`job_name` varchar(100) NULL DEFAULT NULL COMMENT '任务名称',
`cron_expression` varchar(255) NULL DEFAULT NULL COMMENT 'cron表达式',
`bean_class` varchar(255) NULL DEFAULT NULL COMMENT '任务执行类(包名+类名)',
`status` varchar(10) NULL DEFAULT NULL COMMENT '任务状态',
`job_group` varchar(50) NULL DEFAULT NULL COMMENT '任务分组',
`job_data_map` varchar(1000) NULL DEFAULT NULL COMMENT '参数',
`create_user_id` int(0) NULL DEFAULT NULL COMMENT '创建人ID',
`create_date` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_user_id` int(0) NULL DEFAULT NULL COMMENT '更新人ID',
`update_date` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
`remarks` varchar(255) NULL DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`) USING BTREE
) AUTO_INCREMENT = 3 COMMENT = '定时任务';
-- ----------------------------
-- Records of t_sys_job
-- ----------------------------
INSERT INTO `t_sys_job` VALUES (1, 'TestJob', '0/5 * * * * ?', 'com.c3stones.job.biz.TestJob', 'NONE', 'default', '{\"username\":\"zhangsan\", \"age\":18}', 1, '2020-09-25 15:22:32', 1, '2020-09-25 15:22:32', '测试定时任务1');
INSERT INTO `t_sys_job` VALUES (2, 'Test2Job', '0 * * * * ?', 'com.c3stones.job.biz.Test2Job', 'NONE', 'default', '{\"username\":\"lisi\", \"age\":20}', 1, '2020-09-25 15:22:54', 1, '2020-09-25 15:22:54', '测试定时任务2');
-- ----------------------------
-- Table structure for t_sys_user
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user` (
`id` int(0) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`username` varchar(50) NULL DEFAULT NULL COMMENT '用户名称',
`nickname` varchar(100) NULL DEFAULT NULL COMMENT '用户昵称',
`password` varchar(255) NULL DEFAULT NULL COMMENT '用户密码',
PRIMARY KEY (`id`) USING BTREE
)AUTO_INCREMENT = 3 COMMENT = '系统用户';
-- ----------------------------
-- Records of t_sys_user
-- ----------------------------
INSERT INTO `t_sys_user` VALUES (1, 'user', 'C3Stones', '$2a$10$WXEPqxjMwY6d6A0hkeBtGu.acRRWUOJmX7oLUuYMHF1VWWUm4EqOC');
INSERT INTO `t_sys_user` VALUES (2, 'system', '管理员', '$2a$10$dmO7Uk9/lo1D5d1SvCGgWuB050a0E2uuBDNITEpWFiIfCg.3UbA8y');
SET FOREIGN_KEY_CHECKS = 1;
本文在之前博客SpringBoot + Layui +Mybatis-plus实现简单后台管理系统(内置安全过滤器)的示例项目spring-boot-layui-demo基础上增加了任务调度菜单,因此请先下载相关工程。
修改pom.xml
引入依赖spring-boot-starter-quartz
即可实现SpringBoot与Quartz集成。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.8.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
配置文件application.yml添加quartz相关配置
server:
port: 8080
servlet:
session:
timeout: 1800s
spring:
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/quartzdemo?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
username: root
password: 123456
thymeleaf:
prefix: classpath:/view/
suffix: .html
encoding: UTF-8
servlet:
content-type: text/html
# 生产环境设置true
cache: false
quartz:
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: t_qrtz_
isClustered: false
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
job-store-type: jdbc
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
global-config:
db-config:
id-type: AUTO
logging:
config: classpath:logback-spring.xml
security:
web:
excludes:
- /login
- /logout
- /images/**
- /jquery/**
- /layui/**
xss:
enable: true
excludes:
- /login
- /logout
- /images/*
- /jquery/*
- /layui/*
sql:
enable: true
excludes:
- /images/*
- /jquery/*
- /layui/*
csrf:
enable: true
excludes:
创建调度器配置类
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
/**
调度器配置类
*
@author CL
*
*/
@Configuration
public class SchedulerConfig implements SchedulerFactoryBeanCustomizer {
@Autowired
private DataSource dataSource;
@Override
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
// 启动延时
schedulerFactoryBean.setStartupDelay(10);
// 自动启动任务调度
schedulerFactoryBean.setAutoStartup(true);
// 是否覆盖现有作业定义
schedulerFactoryBean.setOverwriteExistingJobs(true);
// 配置数据源
schedulerFactoryBean.setDataSource(dataSource);
}
}
创建全局用户工具类
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.c3stones.sys.entity.User;
/**
用户工具类
*
@author CL
*
*/
public class UserUtils {
/**
/**
/**
}
创建实体
import java.io.Serializable;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
定时任务
*
@author CL
*
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "t_sys_job")
@EqualsAndHashCode(callSuper = false)
public class Job extends Model
private static final long serialVersionUID = 1L;
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
}
创建定时任务处理器
import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.Trigger.TriggerState;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.c3stones.job.entity.Job;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
/**
定时任务管理器
*
@author CL
*
*/
@Slf4j
@Component
public class QuartzHandler {
@Autowired
private Scheduler scheduler;
/**
/**
/**
/**
/**
/**
/***
/**
/**
/**
/**
/**
/**
/**
}
创建Mapper
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.c3stones.job.entity.Job;
/**
}
创建Service
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.c3stones.job.entity.Job;
/**
定时任务Service
*
@author CL
*
*/
public interface JobService extends IService
/**
}
创建Service实现类
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.c3stones.job.config.QuartzHandler;
import com.c3stones.job.entity.Job;
import com.c3stones.job.mapper.JobMapper;
import com.c3stones.job.service.JobService;
import cn.hutool.core.util.StrUtil;
/**
定时任务Service实现
*
@author CL
*
*/
@Service
public class JobServiceImpl extends ServiceImpl
@Autowired
private QuartzHandler quartzHandler;
/**
查询列表数据
*
@param job 系统用户
@param current 当前页
@param size 每页显示条数
@return
*/
@Override
public Page
QueryWrapper
if (StrUtil.isNotBlank(job.getJobName())) {
queryWrapper.like("job_name", job.getJobName());
}
Page
List
// 处理定时任务数据
for (int i = 0; i < records.size(); i++) {
Job j = records.get(i);
// 获取下一次执行时间
j.setNextfireDate(quartzHandler.nextfireDate(j.getCronExpression()));
// 更新状态
String status = quartzHandler.getStatus(j);
if (!(status).equals(j.getStatus())) {
j.setStatus(status);
super.updateById(j);
}
records.set(i, j);
}
page.setRecords(records);
return page;
}
}
创建Controller
import java.time.LocalDateTime;
import org.quartz.Trigger.TriggerState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.c3stones.common.vo.Response;
import com.c3stones.job.config.QuartzHandler;
import com.c3stones.job.entity.Job;
import com.c3stones.job.service.JobService;
import com.c3stones.sys.entity.User;
import com.c3stones.sys.utils.UserUtils;
/**
定时任务Controller
*
@author CL
*
*/
@Controller
@RequestMapping(value = "job")
public class JobController {
@Autowired
private QuartzHandler quartzHandler;
@Autowired
private JobService jobService;
/**
/**
/**
/**
/**
/**
暂停
*
@param job 定时任务
@return
*/
@RequestMapping(value = "pasue")
@ResponseBody
public Response
Assert.notNull(job.getId(), "ID不能为空");
Job queryJob = jobService.getById(job.getId());
Assert.notNull(queryJob, "定时任务不存在");
String status = quartzHandler.getStatus(queryJob);
if (!((TriggerState.NORMAL.toString()).equals(status) || (TriggerState.PAUSED.toString()).equals(status)
|| (TriggerState.BLOCKED.toString()).equals(status))) {
return Response.success("当前状态不可暂停", false);
}
if ((TriggerState.PAUSED.toString()).equals(status)) {
return Response.success("已暂停", false);
}
boolean result = quartzHandler.pasue(queryJob);
return Response.success("暂停" + (result ? "成功" : "失败"), result);
}
/**
立即执行
*
@param job 定时任务
@return
*/
@RequestMapping(value = "trigger")
@ResponseBody
public Response
Assert.notNull(job.getId(), "ID不能为空");
Job queryJob = jobService.getById(job.getId());
Assert.notNull(queryJob, "定时任务不存在");
String status = quartzHandler.getStatus(queryJob);
if (!((TriggerState.NORMAL.toString()).equals(status) || (TriggerState.PAUSED.toString()).equals(status)
|| (TriggerState.COMPLETE.toString()).equals(status))) {
return Response.success("当前状态不可立即执行", false);
}
boolean result = quartzHandler.trigger(queryJob);
return Response.success("立即执行" + (result ? "成功" : "失败"), result);
}
/**
/**
/**
/**
/**
}
主页index.html配置菜单
<div class="layui-side custom-admin">
<div class="layui-side-scroll">
<div class="custom-logo">
<img alt="" th:src="@{/images/logo.jpg}">
<h1>C3Stones</h1>
</div>
<ul id="Nav" class="layui-nav layui-nav-tree">
<li class="layui-nav-item">
<a href="javascript:;">
<i class="layui-icon"></i>
<em>主页</em>
</a>
<dl class="layui-nav-child">
<dd><a th:href="@{/view}">控制台</a></dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="javascript:;">
<i class="layui-icon"></i>
<em>系统管理</em>
</a>
<dl class="layui-nav-child">
<dd><a th:href="@{/user/list}">用户管理</a></dd>
</dl>
<dl class="layui-nav-child">
<dd><a th:href="@{/job/list}">任务调度</a></dd>
</dl>
</li>
</ul> </div>
</div>
<div class="layui-body">
<div class="layui-tab app-container" lay-allowClose="true" lay-filter="tabs">
<ul id="appTabs" class="layui-tab-title custom-tab"></ul>
<div id="appTabPage" class="layui-tab-content"></div>
</div>
</div>
<div class="layui-footer">
<p> 2020 - C3Stones Blog : <a href="https://www.cnblogs.com/cao-lei/" target="_blank">https://www.cnblogs.com/cao-lei/</a></p>
</div>
<div class="mobile-mask"></div>
</div>
新增定时任务列表页面jobList.html
新增定时任务新增页面jobAdd.html
创建两种类型Job
实现Job接口
import java.time.LocalDateTime;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import com.c3stones.job.service.JobService;
import lombok.extern.slf4j.Slf4j;
/**
测试定时任务
*
@author CL
*
*/
@Slf4j
// @DisallowConcurrentExecution //不并发执行
public class TestJob implements Job {
@Autowired
private JobService jobService;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap jobDataMap = context.getMergedJobDataMap();
log.info("定时任务1 => 定时任务定时任务数量 => {},参数值 => {},当前时间 => {}", jobService.count(),
"{ username=" + jobDataMap.get("username") + ", age=" + jobDataMap.get("age") + " }",
LocalDateTime.now());
}
}
继承QuartzJobBean类
import java.time.LocalDateTime;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.c3stones.job.service.JobService;
import lombok.extern.slf4j.Slf4j;
/**
测试定时任务
*
@author CL
*
*/
@Slf4j
// @DisallowConcurrentExecution //不并发执行
public class Test2Job extends QuartzJobBean {
@Autowired
private JobService jobService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
JobDataMap jobDataMap = context.getMergedJobDataMap();
log.info("定时任务2 => 定时任务数量 => {},参数值 => {},当前时间 => {}", jobService.count(),
"{ username=" + jobDataMap.get("username") + ", age=" + jobDataMap.get("age") + " }",
LocalDateTime.now());
}
}
配置定时任务
浏览器访问:http://127.0.0.1:8080/login,填写用户信息user/123456登录系统,点击菜单:系统管理>任务调度,通过新增页面,添加两个定时任务。配置完成页面如下:
顶部按钮:定时器待机
和启动定时器
为定时器操作按钮,即对所有定时任务有效。当定时器状态为启动中时,定时器待机
显示,点击定时器状态变为待机中,所有定时任务待机;反之,所有定时任务可正常触发。
右侧操作栏按钮:启动
、暂停
、立即执行
和删除
,仅对当前定时任务有效。新增完的定时任务为未启动状态,点击启动
按钮即可触发定时任务,点击暂停
按钮即可暂停定时任务,点击立即执行
按钮即可立即执行一次定时任务,点击删除
按钮即可删除定时任务。
点击操作按钮,观察控制台日志打印
手机扫一扫
移动阅读更方便
你可能感兴趣的文章