博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
quartz整合springboot实现动态配置任务的CRUD详情操作
阅读量:4165 次
发布时间:2019-05-26

本文共 12750 字,大约阅读时间需要 42 分钟。

quartz整合springboot实现动态配置任务的CRUD详情操作

文章目录

quartz整合springboot完成动态的配置定时任务的CRUD

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。

一、quartz中相关介绍

Quartz API

Quartz API的关键接口是:

  • Scheduler - 与调度程序交互的主要API。
  • Job - 由希望由调度程序执行的组件实现的接口。
  • JobDetail - 用于定义作业的实例。
  • Trigger(即触发器) - 定义执行给定作业的计划的组件。
  • JobBuilder - 用于定义/构建JobDetail实例,用于定义作业的实例。
  • TriggerBuilder - 用于定义/构建触发器实例。

调度器 scheduler:

Scheduler:调度器。所有的调度都是由它控制       Scheduler就是Quartz的大脑,所有任务都是由它来设施       Schdue1r包含一个两个重要组件:JobStore和ThreadPool           JobStore是会来存储运行时信息的,包括Trigger,Schduler,JobDetai1,业务锁等           ThreadPoo1就是线程池,Quartz有自己的线程池实现。所有任务的都会由线程池执行       SchdulerFactory,顾名思义就是来用创建Schduler了,           有两个实现:DirectSchedulerFactory和StdSchdulerFactory。           前者可以用来在代码里定制你自己的Schduler参数。           后者是直接读取classpath下的quartz.properties(不存在就都使用默认值)配置来实例化Schduler.通常来讲,我们使用StdSchdulerFactory也就足够了。      SchdulerFactory本身是支持创建RMI stub的,可以用来管理远程的Scheduler,功能与本地一样

触发器 trigger:

Trigger用于触发Job的执行。当你准备调度一个job时,你创建一个Trigger的实例,然后设置调度相关的属性。Trigger也有一个相关联的JobDataMap,用于给Job传递一些触发相关的参数。Quartz自带了各种不同类型的Trigger,最常用的主要是SimpleTrigger和CronTrigger。SimpleTrigger主要用于一次性执行的Job(只在某个特定的时间点执行一次),或者Job在特定的时间点执行,重复执行N次,每次执行间隔T个时间单位。CronTrigger在基于日历的调度上非常有用,如“每个星期五的正午”,或者“每月的第十天的上午10:15”等。为什么既有Job,又有Trigger呢?很多任务调度器并不区分Job和Trigger。有些调度器只是简单地通过一个执行时间和一些job标识符来定义一个Job;其它的一些调度器将Quartz的Job和Trigger对象合二为一。在开发Quartz的时候,我们认为将调度和要调度的任务分离是合理的。在我们看来,这可以带来很多好处。例如,Job被创建后,可以保存在Scheduler中,与Trigger是独立的,同一个Job可以有多个Trigger;这种松耦合的另一个好处是,当与Scheduler中的Job关联的trigger都过期时,可以配置Job稍后被重新调度,而不用重新定义Job;还有,可以修改或者替换Trigger,而不用重新定义与之关联的Job。

任务job:

当Job的一个trigger被触发时,execute()方法由调度程序的一个工作线程调用。传递给execute()方法的JobExecutionContext对象向作业实例提供有关其“运行时”环job的一个trigger被触发后,execute()方法会被scheduler的一个工作线程调用;传递给execute()方法的JobExecutionContext对象中保存着该job运行时的一些信息 ,执行job的scheduler的引用,触发job的trigger的引用,JobDetail对象引用,以及一些其它信息。JobDetail对象是在将job加入scheduler时,由客户端程序(你的程序)创建的。它包含job的各种属性设置,以及用于存储job实例状态信息的JobDataMap。

二、quartz整合springboot实现动态配置任务的CRUD

1、导入jar包

org.springframework.boot
spring-boot-starter-quartz

2.相关代码( 这里用到了 SpringDataJpa 操作数据库 )

2.1定时任务实体类:

import lombok.Data;import org.springframework.data.annotation.CreatedBy;import org.springframework.data.annotation.CreatedDate;import org.springframework.data.annotation.LastModifiedBy;import org.springframework.data.annotation.LastModifiedDate;import org.springframework.data.jpa.domain.support.AuditingEntityListener;import javax.persistence.*;import java.util.Date;/** * @author zb * @date 2020/2/21 20:15 * @Description: 定时任务实体类 */@Data@EntityListeners(AuditingEntityListener.class)@Entitypublic class QuartzJob {
/**id*/ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; /**创建人*/ @CreatedBy private String createBy; /**创建时间*/ @CreatedDate private Date createTime; /**修改人*/ @LastModifiedBy private String updateBy; /**修改时间*/ @LastModifiedDate private Date updateTime; /**删除状态 0 表示未删除,1 表示已删除*/ private Integer delFlag = 0; /**任务类名*/ private String jobClassName; /**cron表达式*/ private String cronExpression; /**传入参数*/ private String parameter; /**描述*/ private String description; /**状态 0正常 -1停止*/ private Integer status = 0;}

2.2 service实现类(dao 层 Repository 类这里省略)

import cn.hutool.core.util.StrUtil;import cn.mesmile.querydslx.module.common.PaginationResponse;import cn.mesmile.querydslx.module.quartz.common.CommonConstant;import cn.mesmile.querydslx.module.quartz.dao.QuartzJobRepository;import cn.mesmile.querydslx.module.quartz.domain.QuartzJob;import cn.mesmile.querydslx.module.quartz.dto.QuartzJobQueryReq;import cn.mesmile.querydslx.module.quartz.exception.QuartzTaskException;import cn.mesmile.querydslx.module.quartz.service.QuartzJobService;import com.github.wenhao.jpa.Specifications;import lombok.extern.slf4j.Slf4j;import org.quartz.*;import org.quartz.impl.matchers.GroupMatcher;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageRequest;import org.springframework.data.jpa.domain.Specification;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import java.util.List;import java.util.Optional;/** * @author zb * @date 2020/2/19 20:31 * @Description: Copyright (C),2020,AOSSCI Inc.傲势科技有限公司 */@Slf4j@Transactional(propagation = Propagation.SUPPORTS,readOnly = true,rollbackFor = Exception.class)@Servicepublic class QuartzJobServiceImpl implements QuartzJobService {
@Autowired private QuartzJobRepository quartzJobRepository; @Autowired private Scheduler scheduler; /** * 保存&启动定时任务 */ @Transactional(rollbackFor = Exception.class) @Override public boolean saveAndScheduleJob(QuartzJob quartzJob) throws QuartzTaskException {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
// 定时器添加 this.schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter()); } // DB设置修改 未删除 quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0); // 保存定时任务 quartzJobRepository.save(quartzJob); return true; } /** * 恢复定时任务 */ @Override public boolean resumeJob(QuartzJob quartzJob) throws QuartzTaskException {
// 先删除 schedulerDelete(quartzJob.getJobClassName().trim()); // 添加定时任务 schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter()); Optional
optionalQuartzJob = quartzJobRepository.findById(quartzJob.getId()); if( !optionalQuartzJob.isPresent()) {
return false; } QuartzJob quartzJob2 = optionalQuartzJob.get(); // 将状态设置为正常 quartzJob2.setStatus(CommonConstant.STATUS_NORMAL); quartzJobRepository.save(quartzJob2); return true; } @Override public QuartzJob getById(Long id) {
Optional
optional = quartzJobRepository.findById(id); return optional.orElse(null); } /** * 编辑定时任务 * @throws SchedulerException */ @Transactional(rollbackFor = Exception.class) @Override public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException, QuartzTaskException {
if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
// 若状态为【非正常】则先删除原来的 schedulerDelete(quartzJob.getJobClassName().trim()); // 再添加新 schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter()); }else{
// 恢复任务 scheduler.pauseJob(JobKey.jobKey(quartzJob.getJobClassName().trim())); } Optional
optionalQuartzJob = quartzJobRepository.findById(quartzJob.getId()); if (optionalQuartzJob.isPresent()) {
QuartzJob quartzJob2 = optionalQuartzJob.get(); // 修改任务 BeanUtils.copyProperties(quartzJob,quartzJob2); quartzJobRepository.save(quartzJob2); } return true; } /** * 删除并停止删除定时任务 */ @Override public boolean deleteAndStopJob(QuartzJob job) throws QuartzTaskException {
// 删除任务 schedulerDelete(job.getJobClassName().trim()); Optional
optionalQuartzJob = quartzJobRepository.findById(job.getId()); if (optionalQuartzJob.isPresent()) {
QuartzJob quartzJob2 = optionalQuartzJob.get(); // 修改为删除状态 quartzJob2.setDelFlag(1); quartzJobRepository.save(quartzJob2); } return true; } /** * 添加定时任务 * * @param jobClassName 例:cn.mesmile.quartz.job.SampleJob SampleJob类需要实现 quartz 中的 Job 接口,然后覆写 execute 方法,在此方法中实现我们需要执行的任务 具体看第 2.3 步。 * @param cronExpression 例:cron 表达式 * * * * * ? * * @param parameter 例:执行此方法需要传入的参数 */ private void schedulerAdd(String jobClassName, String cronExpression, String parameter) throws QuartzTaskException {
try {
// ① 启动调度器 scheduler.start(); // ② 构建job信息 JobDetail jobDetail = JobBuilder.newJob( getClass(jobClassName).getClass() ) .withIdentity(jobClassName) // .storeDurably(true) 持久储存 .usingJobData("parameter", parameter) .build(); // 表达式调度构建器(即任务执行的时间) CronScheduleBuilder scheduleBuilder = CronScheduleBuilder .cronSchedule(cronExpression); // ③ 按新的cronExpression表达式构建一个新的trigger CronTrigger trigger = TriggerBuilder.newTrigger() .withIdentity(jobClassName) .withSchedule(scheduleBuilder) .build(); // ④ 调度器中加入 任务 和 触发器 scheduler.scheduleJob(jobDetail, trigger); /* 三种监听器: ① JobListener 任务监听器 ② TriggerListener 触发监听器 ③ SchedulerListener 调度监听器 */ /* JobListener 1)getName方法:用于获取该JobListener的名称。 2)jobToBeExecuted方法:Scheduler在JobDetail将要被执行时调用这个方法。 3)jobExecutionVetoed方悉:Scheduler在JobDetail即将被执行,但又被TriggerListener否决时会调用该方法 4)jobWasExecuted方法:Scheduler在JobDetail被执行之后调用这个方法 */ // 注册一个全局的监听器 MyJobListen 实现 JobListen // scheduler.getListenerManager().addJobListener(new MyJobListener(), EverythingMatcher.allJobs()); // 注册一个局部 // scheduler.getListenerManager().addJobListener(new MyJobListener(), KeyMatcher.keyEquals(JobKey.jobKey("",""))); } catch (SchedulerException e) {
throw new QuartzTaskException("创建定时任务失败", e); } catch (RuntimeException e) {
throw new QuartzTaskException(e.getMessage(), e); }catch (Exception e) {
throw new QuartzTaskException("后台找不到该类名:" + jobClassName, e); } } /** * 删除定时任务 * * @param jobClassName 例如:cn.mesmile.quartz.job. */ private void schedulerDelete(String jobClassName) throws QuartzTaskException {
try {
// 暂停触发器 scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName)); // 解除任务调度器 scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName)); // 删除任务 scheduler.deleteJob(JobKey.jobKey(jobClassName)); } catch (Exception e) {
log.error(e.getMessage(), e); throw new QuartzTaskException("删除定时任务失败"); } } // 通过包名 反射获得 对象 private static Job getClass(String classname) throws Exception {
Class
class1 = Class.forName(classname); return (Job) class1.newInstance(); }}

2.3设置需要执行任务的类

​ (1) 无参数传入任务

import cn.hutool.core.date.DateUtil;import lombok.extern.slf4j.Slf4j;import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;/** * @author zb * @date 2020/2/21 20:33 * @Description: 无参数传入任务, 需要实现quartz中的 Job 接口 */@Slf4jpublic class SampleJob implements Job {
@Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("------------- 这里执行了普通无参定时任务 ! 时间: {}" , DateUtil.now() ); }}

(2)有参数传入任务

import cn.hutool.core.date.DateUtil;import lombok.extern.slf4j.Slf4j;import org.quartz.Job;import org.quartz.JobDetail;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;/** * @author zb * @date 2020/2/21 20:38 * @Description: 有参数定时任务, 需要实现quartz中的 Job 接口 */@Slf4jpublic class SampleParamJob implements Job {
/** * 传入参数名 和 service实现类中 添加任务时设定的参数 parameter 名称要一致 */ private String parameter; public void setParameter(String parameter) {
this.parameter = parameter; } @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
// 创建工作详情 JobDetail jobDetail = jobExecutionContext.getJobDetail(); // 任务名 String name = jobDetail.getKey().getName(); // 任务分组 String group = jobDetail.getKey().getGroup(); // 任务中的数据 String parameter = jobDetail.getJobDataMap().getString("parameter"); log.info("job执行 SampleParamJob 有参数传入,任务名:{} , 分组group: {}, 数据data: {} , 时间: {} ", name, group , parameter, DateUtil.now()); }}

转载地址:http://uhxxi.baihongyu.com/

你可能感兴趣的文章
Linux永久后台启动程序nohup commmand &
查看>>
HTTP请求支持keep-alive
查看>>
autogen.sh 的使用
查看>>
ios使用VoIP推送通知
查看>>
HTTP之put/post请求头中的Expect:100-continue
查看>>
通过https发请求时出现“curle_out_of_memory”错误
查看>>
Linux编译libcurl依赖openssl和cares
查看>>
Excel中按照数字和汉字列对所有列排序
查看>>
go语言实现两个goroutine交替执行打印数字和字母,效果:12AB34CD56EF...
查看>>
Go语言websocket (一)
查看>>
多房间聊天室 websocket(一)
查看>>
go语言多房间聊天室websocket(二)
查看>>
Golang实现输入两个日期时间转换为周时间
查看>>
2002 - Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13 "权限不够")
查看>>
k8s外部访问的几种方法实践
查看>>
Unable to connect to the server: x509: certificate has expired or is not yet valid
查看>>
Python字符串操作大全(一)
查看>>
Python字符串操作全(二)
查看>>
爬虫:python爬取 糗事百科 网页信息
查看>>
VMware 虚拟机ubuntu安装linux(一)
查看>>