SpringBoot技术专题「开发实战系列」动态化Quartz任务调度机制+实时推送任务数据到前端
Posted 洛神灬殇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot技术专题「开发实战系列」动态化Quartz任务调度机制+实时推送任务数据到前端相关的知识,希望对你有一定的参考价值。
前提介绍
SpringBoot2.0整合quartz实现多定时任务动态配置,实现任务增删改,生成Cron表达式
动态化任务调度
添加依赖包
<!-- quartz -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
DynamicSchedulerConfig
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class DynamicSchedulerConfig implements SchedulerFactoryBeanCustomizer
@Override
public void customize(SchedulerFactoryBean schedulerFactoryBean)
schedulerFactoryBean.setStartupDelay(2);
schedulerFactoryBean.setAutoStartup(true);
schedulerFactoryBean.setOverwriteExistingJobs(true);
application.yml配置
server:
port: 8101
# 默认的profile为dev,其他环境通过指定启动参数使用不同的profile,比如:
# 测试环境:java -jar quartz-service.jar --spring.profiles.active=test
# 生产环境:java -jar quartz-service.jar --spring.profiles.active=prod
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#这里是配置druid连接池,以下都是druid的配置信息
url: jdbc:mysql://127.0.0.1:3306/task?useUnicode=true&characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
#quartz相关属性配置
quartz:
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
#数据库方式
job-store-type: jdbc
# mybatisplus配置
mybatis-plus:
mapper-locations: classpath*:/mapper/**Mapper.xml
#把xml文件放在com.XX.mapper.*中可能会出现找到的问题,这里把他放在resource下的mapper中
typeAliasesPackage: com.task.entity
#这里是实体类的位置,#实体扫描,多个package用逗号或者分号分隔
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
logging:
file: task-info.log
level:
com.task: debug
TaskInfoService业务服务类
@Service
public class TaskInfoService extends IService<TaskInfoBO>
/**
* @Title: getPageJob
* @Description: TODO(查询定时任务,分页)
* @param @param search
* @param @return 参数
* @return Map<String,Object> 返回类型
* @throws
*/
IPage<TaskInfoBO> getPageJob(Pageable pageable, MultiValueMap queryParam);
/**
* @Title: getPageJobmod
* @Description: TODO(查询定时任务)
* @param @return 参数
* @return TaskInfoBO 返回类型
* @throws
*/
TaskInfoBO getPageJobmod();
/**
* @Title: addJob
* @Description: TODO(添加任务)
* @param @param jobClassName 任务路径名称
* @param @param jobGroupName 任务分组
* @param @param cronExpression cron时间规则
* @param @throws Exception 参数
* @return void 返回类型
* @throws
*/
void addJob(String jobClassName, String jobGroupName, String cronExpression) throws Exception;
/**
* @Title: addJob
* @Description: TODO(添加动态任务)
* @param @param jobClassName 任务路径名称
* @param @param jobGroupName 任务分组
* @param @param cronExpression cron时间规则
* @param @param jobDescription 参数
* @param @param params
* @param @throws Exception 参数说明
* @return void 返回类型
* @throws
*/
void addJob(String jobClassName, String jobGroupName, String cronExpression, String jobDescription, Map<String, Object> params) throws Exception;
/**
* @Title: updateJob
* @Description: TODO(更新定时任务)
* @param @param jobClassName 任务路径名称
* @param @param jobGroupName 任务分组
* @param @param cronExpression cron时间规则
* @param @throws Exception 参数
* @return void 返回类型
* @throws
*/
void updateJob(String jobClassName, String jobGroupName, String cronExpression) throws Exception;
/**
* @Title: deleteJob
* @Description: TODO(删除定时任务)
* @param @param jobClassName 任务路径名称
* @param @param jobGroupName 任务分组
* @param @throws Exception 参数
* @return void 返回类型
* @throws
*/
void deleteJob(String jobClassName, String jobGroupName) throws Exception;
/**
* @Title: pauseJob
* @Description: TODO(暂停定时任务)
* @param @param jobClassName 任务路径名称
* @param @param jobGroupName 任务分组
* @param @throws Exception 参数
* @return void 返回类型
* @throws
*/
void pauseJob(String jobClassName, String jobGroupName) throws Exception;
/**
* @Title: resumejob
* @Description: TODO(恢复任务)
* @param @param jobClassName 任务路径名称
* @param @param jobGroupName 任务分组
* @param @throws Exception 参数
* @return void 返回类型
* @throws
*/
void resumejob(String jobClassName, String jobGroupName) throws Exception;
TaskInfoServiceImpl业务服务类
@Slf4j
@Service
@Transactional
public class TaskInfoServiceImpl extends ServiceImpl<JobAndTriggerMapper, TaskInfoBO> implements TaskInfoService
@Autowired
private Scheduler scheduler;
@Override
public IPage<TaskInfoBO> getPageJob(Pageable pageable, MultiValueMap queryParam)
IPage<TaskInfoBO> page = new Page<>(pageable.getPageNumber(), pageable.getPageSize());
return baseMapper.getJobAndTriggerDetails(page);
@Override
public TaskInfoBO getPageJobmod()
return baseMapper.getJobAndTriggerDto();
@Override
public void addJob(String jobClassName, String jobGroupName, String cronExpression) throws Exception
// 启动调度器
scheduler.start();
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
.withIdentity(jobClassName, jobGroupName).build();
// 表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
.withSchedule(scheduleBuilder).build();
try
scheduler.scheduleJob(jobDetail, trigger);
catch (SchedulerException e)
throw new Exception("创建定时任务失败");
@Override
public void addJob(String jobClassName, String jobGroupName, String cronExpression, String jobDescription,
Map<String, Object> params) throws Exception
// 启动调度器
scheduler.start();
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(TaskInfoServiceImpl.getClass(jobClassName).getClass())
.withIdentity(jobClassName, jobGroupName).withDescription(jobDescription).build();
Iterator<Map.Entry<String, Object>> var7 = params.entrySet().iterator();
while(var7.hasNext())
Map.Entry<String, Object> entry = var7.next();
jobDetail.getJobDataMap().put((String)entry.getKey(), entry.getValue());
// 表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
// 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = (CronTrigger)TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
.withSchedule(scheduleBuilder).build();
try
scheduler.scheduleJob(jobDetail, trigger);
catch (SchedulerException e)
throw new Exception("创建定时任务失败");
@Override
public void updateJob(String jobClassName, String jobGroupName, String cronExpression) throws Exception
try
TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
// 表达式调度构建器(动态修改后不立即执行)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(triggerKey, trigger);
catch (SchedulerException e)
throw new Exception("更新定时任务失败");
@Override
public void deleteJob(String jobClassName, String jobGroupName) throws Exception
scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
@Override
public void pauseJob(String jobClassName, String jobGroupName) throws Exception
scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
@Override
public void resumejob(String jobClassName, String jobGroupName) throws Exception
scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
public static BaseJob getClass(String classname) throws Exception
Class<?> class1 = Class.forName(classname);
return (BaseJob) class1.newInstance();
TaskInfoMapper
public interface JobAndTriggerMapper extends BaseMapper<TaskInfoBO>
IPage<TaskInfoBO> getJobAndTriggerDetails(IPage<TaskInfoBO> page);
TaskInfoBO getTaskInfoModel;
TaskInfoMapper.xml
<?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.south.data.mapper.JobAndTriggerMapper">
<select id="getJobAndTriggerDetails" resultType="com.data.vo.TaskInfoBO">
SELECT
jd.JOB_NAME AS jobName,
jd.DESCRIPTION AS jobDescription,
jd.JOB_GROUP AS jobGroupName,
jd.JOB_CLASS_NAME AS jobClassName,
t.TRIGGER_NAME AS triggerName,
t.TRIGGER_GROUP AS triggerGroupName,
FROM_UNIXTIME(t.PREV_FIRE_TIME/1000,'%Y-%m-%d %T') AS prevFireTime,
FROM_UNIXTIME(t.NEXT_FIRE_TIME/1000,'%Y-%m-%d %T') AS nextFireTime,
ct.CRON_EXPRESSION AS cronExpression,
t.TRIGGER_STATE AS triggerState
FROM
qrtz_job_details jd
JOIN qrtz_triggers t
JOIN qrtz_cron_triggers ct ON jd.JOB_NAME = t.JOB_NAME
AND t.TRIGGER_NAME = ct.TRIGGER_NAME
AND t.TRIGGER_GROUP = ct.TRIGGER_GROUP
</select>
<select id="getJobAndTriggerDto" resultType="com.south.data.vo.JobAndTriggerDto">
SELECT
jd.JOB_NAME AS jobName,
jd.DESCRIPTION AS jobDescription,
jd.JOB_GROUP AS jobGroupName,
jd.JOB_CLASS_NAME AS jobClassName,
t.TRIGGER_NAME AS triggerName,
t.TRIGGER_GROUP AS triggerGroupName,
FROM_UNIXTIME(t.PREV_FIRE_TIME/1000,'%Y-%m-%d %T') AS prevFireTime,
FROM_UNIXTIME(t.NEXT_FIRE_TIME/1000,'%Y-%m-%d %T') AS nextFireTime,
ct.CRON_EXPRESSION AS cronExpression,
t.TRIGGER_STATE AS triggerState
FROM
qrtz_job_details jd
JOIN qrtz_triggers t
JOIN qrtz_cron_triggers ct ON jd.JOB_NAME = t.JOB_NAME
AND t.TRIGGER_NAME = ct.TRIGGER_NAME
AND t.TRIGGER_GROUP = ct.TRIGGER_GROUP
</select>
</mapper>
BaseJob类
public interface BaseJob extends Job
public void execute(JobExecutionContext context) throws JobExecutionException;
TaskController控制器
@RestController
@RequestMapping(value = "/job")
public class JobController
@Autowired
private TaskInfoService taskInfoService;
public JobController(TaskInfoService taskInfoService)
this.taskInfoService = taskInfoService;
@PostMapping(value = "/page")
public ResponseEntity<List<TaskInfoBO>> queryjob(Pageable pageable, @RequestParam MultiValueMap<String, String> queryParams, UriComponentsBuilder uriBuilder)
IPage<TaskInfoBO> page = taskInfoService.getPageJob(pageable, queryParams);
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(uriBuilder.queryParams(queryParams), page);
return ResponseEntity.ok().headers(headers).body(page.getRecords());
/**
* @Title: addJob
* @Description: TODO(添加Job)
* @param jobClassName
* 类名
* @param jobGroupName
* 组名
* @param cronExpression
* 表达式,如:0/5 * * * * ? (每隔5秒)
*/
@PostMapping(value = "/add")
public ResponseEntity addJob(
@RequestParam(value = "jobClassName") String jobClassName,
@RequestParam(value = "jobGroupName") String jobGroupName,
@RequestParam(value = "cronExpression") String cronExpression)
try
jobAndTriggerService.addJob(jobClassName, jobGroupName, cronExpression);
return ResponseEntity.ok().body("操作成功");
catch (Exception e)
return ResponseEntity.ok().body("操作失败");
/**
* @Title: pauseJob
* @Description: TODO(暂停Job)
* @param jobClassName
* 类名
* @param jobGroupName
* 组名
*/
@PostMapping(value = "/pause")
public ResponseEntity pauseJob(
@RequestParam(value = "jobClassName") String jobClassName,
@RequestParam(value = "jobGroupName") String jobGroupName)
try
taskInfoService.pauseJob(jobClassName, jobGroupName);
return ResponseEntity.ok().body("操作成功");
catch (Exception e)
return ResponseEntity.ok().body("操作失败");
/**
* @Title: resumeJob
* @Description: TODO(恢复Job)
* @param jobClassName
* 类名
* @param jobGroupName
* 组名
*/
@PostMapping(value = "/resume")
public ResponseEntity resumeJob(
@RequestParam(value = "jobClassName") String jobClassName,
@RequestParam(value = "jobGroupName") String jobGroupName)
try
taskInfoService.resumejob(jobClassName, jobGroupName);
return ResponseEntity.ok()以上是关于SpringBoot技术专题「开发实战系列」动态化Quartz任务调度机制+实时推送任务数据到前端的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot技术专题「开发实战系列」一起搭建属于自己的SpringBoot Admin的技术要素
SpringBoot技术专题「实战开发系列」带你一同探索Shiro整合JWT授权和认证实战开发
SpringBoot技术专题「开发实战系列」一起搭建属于自己的SpringBoot Admin的技术要素
SpringBoot技术专题「开发实战系列」全面梳理和分析一下相关的Web核心配置