1、QuartJob简介

Quartz是一个完全由java编写的开源作业调度框架,形式简易,功能强大。

1.1 核心API

  1. Scheduler

    代表一个 Quartz 的独立运行容器,Scheduler 将 Trigger 绑定到特定 JobDetail, 这样当 Trigger 触发时, 对应的 Job 就会被调度。
  2. Trigger

    描述 Job 执行的时间触发规则。主要有 SimpleTrigger 和 CronTrigger 两个子类,通过一个 TriggerKey 唯一标识。
  3. Job

    定义一个任务,规定了任务是执行时的行为。JobExecutionContext 提供了调度器的上下文信息,Job 的数据可从 JobDataMap 中获取。
  4. JobDetail

    Quartz 在每次执行 Job 时,都重新创建一个 Job 实例,所以它不直接接受一个 Job 的实例,相反它接收一个 Job 实现类。描述 Job 的实现类及其它相关的静态信息,如 Job 名字、描述等。

2、SpringBoot整合QuartJob

2.1 项目结构

版本描述

spring-boot:2.1.3.RELEASE
quart-job:2.3.0

2.2 定时器配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
public class ScheduleConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
// Quartz参数配置
Properties prop = new Properties();
// Schedule调度器的实体名字
prop.put("org.quartz.scheduler.instanceName", "HuskyScheduler");
// 设置为AUTO时使用,默认的实现org.quartz.scheduler.SimpleInstanceGenerator是基于主机名称和时间戳生成。
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 线程池配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "20");
prop.put("org.quartz.threadPool.threadPriority", "5");
// JobStore配置:Scheduler在运行时用来存储相关的信息
// JDBCJobStore和JobStoreTX都使用关系数据库来存储Schedule相关的信息。
// JobStoreTX在每次执行任务后都使用commit或者rollback来提交更改。
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
// 集群配置:如果有多个调度器实体的话则必须设置为true
prop.put("org.quartz.jobStore.isClustered", "true");
// 集群配置:检查集群下的其他调度器实体的时间间隔
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
// 设置一个频度(毫秒),用于实例报告给集群中的其他实例
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
// 触发器触发失败后再次触犯的时间间隔
prop.put("org.quartz.jobStore.misfireThreshold", "12000");
// 数据库表前缀
prop.put("org.quartz.jobStore.tablePrefix", "qrtz_");
// 从 LOCKS 表查询一行并对这行记录加锁的 SQL 语句
prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); // 定时器工厂配置
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
factory.setQuartzProperties(prop);
factory.setSchedulerName("HuskyScheduler");
factory.setStartupDelay(30);
factory.setApplicationContextSchedulerContextKey("applicationContextKey");
// 可选,QuartzScheduler 启动时更新己存在的Job
factory.setOverwriteExistingJobs(true);
// 设置自动启动,默认为true
factory.setAutoStartup(true);
return factory;
}
}

2.3 定时器管理工具

import com.quart.job.entity.ScheduleJobBean;
import org.quartz.*;
/**
* 定时器工具类
*/
public class ScheduleUtil {
private ScheduleUtil (){}
private static final String SCHEDULE_NAME = "HUSKY_" ;
/**
* 触发器 KEY
*/
public static TriggerKey getTriggerKey(Long jobId){
return TriggerKey.triggerKey(SCHEDULE_NAME+jobId) ;
}
/**
* 定时器 Key
*/
public static JobKey getJobKey (Long jobId){
return JobKey.jobKey(SCHEDULE_NAME+jobId) ;
}
/**
* 表达式触发器
*/
public static CronTrigger getCronTrigger (Scheduler scheduler,Long jobId){
try {
return (CronTrigger)scheduler.getTrigger(getTriggerKey(jobId)) ;
} catch (SchedulerException e){
throw new RuntimeException("getCronTrigger Fail",e) ;
}
}
/**
* 创建定时器
*/
public static void createJob (Scheduler scheduler, ScheduleJobBean scheduleJob){
try {
// 构建定时器
JobDetail jobDetail = JobBuilder.newJob(TaskJobLog.class).withIdentity(getJobKey(scheduleJob.getJobId())).build() ;
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing() ;
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(getTriggerKey(scheduleJob.getJobId()))
.withSchedule(scheduleBuilder).build() ;
jobDetail.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob);
scheduler.scheduleJob(jobDetail,trigger) ;
// 如果该定时器处于暂停状态
if (scheduleJob.getStatus() == 1){
pauseJob(scheduler,scheduleJob.getJobId()) ;
}
} catch (SchedulerException e){
throw new RuntimeException("createJob Fail",e) ;
}
}
/**
* 更新定时任务
*/
public static void updateJob(Scheduler scheduler, ScheduleJobBean scheduleJob) {
try {
// 构建定时器
TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
trigger.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY, scheduleJob);
scheduler.rescheduleJob(triggerKey, trigger);
// 如果该定时器处于暂停状态
if(scheduleJob.getStatus() == 1){
pauseJob(scheduler, scheduleJob.getJobId());
}
} catch (SchedulerException e) {
throw new RuntimeException("updateJob Fail",e) ;
}
}
/**
* 停止定时器
*/
public static void pauseJob (Scheduler scheduler,Long jobId){
try {
scheduler.pauseJob(getJobKey(jobId));
} catch (SchedulerException e){
throw new RuntimeException("pauseJob Fail",e) ;
}
}
/**
* 恢复定时器
*/
public static void resumeJob (Scheduler scheduler,Long jobId){
try {
scheduler.resumeJob(getJobKey(jobId));
} catch (SchedulerException e){
throw new RuntimeException("resumeJob Fail",e) ;
}
}
/**
* 删除定时器
*/
public static void deleteJob (Scheduler scheduler,Long jobId){
try {
scheduler.deleteJob(getJobKey(jobId));
} catch (SchedulerException e){
throw new RuntimeException("deleteJob Fail",e) ;
}
}
/**
* 执行定时器
*/
public static void run (Scheduler scheduler, ScheduleJobBean scheduleJob){
try {
JobDataMap dataMap = new JobDataMap() ;
dataMap.put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob);
scheduler.triggerJob(getJobKey(scheduleJob.getJobId()),dataMap);
} catch (SchedulerException e){
throw new RuntimeException("run Fail",e) ;
}
}
}

2.4 定时器执行和日志

import com.quart.job.entity.ScheduleJobBean;
import com.quart.job.entity.ScheduleJobLogBean;
import com.quart.job.service.ScheduleJobLogService;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
import java.util.Date;
/**
* 定时器执行日志记录
*/
public class TaskJobLog extends QuartzJobBean { private static final Logger LOG = LoggerFactory.getLogger(TaskJobLog.class) ; @Override
protected void executeInternal(JobExecutionContext context) {
ScheduleJobBean jobBean = (ScheduleJobBean)context.getMergedJobDataMap().get(ScheduleJobBean.JOB_PARAM_KEY) ;
ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService)SpringContextUtil.getBean("scheduleJobLogService") ;
// 定时器日志记录
ScheduleJobLogBean logBean = new ScheduleJobLogBean () ;
logBean.setJobId(jobBean.getJobId());
logBean.setBeanName(jobBean.getBeanName());
logBean.setParams(jobBean.getParams());
logBean.setCreateTime(new Date());
long beginTime = System.currentTimeMillis() ;
try {
// 加载并执行定时器的 run 方法
Object target = SpringContextUtil.getBean(jobBean.getBeanName());
Method method = target.getClass().getDeclaredMethod("run", String.class);
method.invoke(target, jobBean.getParams());
long executeTime = System.currentTimeMillis() - beginTime;
logBean.setTimes((int)executeTime);
logBean.setStatus(0);
LOG.info("定时器 === >> "+jobBean.getJobId()+"执行成功,耗时 === >> " + executeTime);
} catch (Exception e){
// 异常信息
long executeTime = System.currentTimeMillis() - beginTime;
logBean.setTimes((int)executeTime);
logBean.setStatus(1);
logBean.setError(e.getMessage());
} finally {
scheduleJobLogService.insert(logBean) ;
}
}
}

3、定时器服务封装

3.1 定时器初始化

@Service
public class ScheduleJobServiceImpl implements ScheduleJobService { @Resource
private Scheduler scheduler ;
@Resource
private ScheduleJobMapper scheduleJobMapper ; /**
* 定时器初始化
*/
@PostConstruct
public void init (){
ScheduleJobExample example = new ScheduleJobExample() ;
List<ScheduleJobBean> scheduleJobBeanList = scheduleJobMapper.selectByExample(example) ;
for (ScheduleJobBean scheduleJobBean : scheduleJobBeanList) {
CronTrigger cronTrigger = ScheduleUtil.getCronTrigger(scheduler,scheduleJobBean.getJobId()) ;
if (cronTrigger == null){
ScheduleUtil.createJob(scheduler,scheduleJobBean);
} else {
ScheduleUtil.updateJob(scheduler,scheduleJobBean);
}
}
}
}

3.2 添加定时器

@Override
@Transactional(rollbackFor = Exception.class)
public int insert(ScheduleJobBean record) {
ScheduleUtil.createJob(scheduler,record);
return scheduleJobMapper.insert(record);
}

3.3 立即执行一次定时器

@Override
@Transactional(rollbackFor = Exception.class)
public void run(Long jobId) {
ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;
ScheduleUtil.run(scheduler,scheduleJobBean);
}

3.4 更新定时器

@Override
@Transactional(rollbackFor = Exception.class)
public int updateByPrimaryKeySelective(ScheduleJobBean record) {
ScheduleUtil.updateJob(scheduler,record);
return scheduleJobMapper.updateByPrimaryKeySelective(record);
}

3.5 停止定时器

@Override
@Transactional(rollbackFor = Exception.class)
public void pauseJob(Long jobId) {
ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;
ScheduleUtil.pauseJob(scheduler,jobId);
scheduleJobBean.setStatus(1);
scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean) ;
}

3.6 恢复定时器

@Override
@Transactional(rollbackFor = Exception.class)
public void resumeJob(Long jobId) {
ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;
ScheduleUtil.resumeJob(scheduler,jobId);
scheduleJobBean.setStatus(0);
scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean) ;
}

3.7 删除定时器

@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Long jobId) {
ScheduleUtil.deleteJob(scheduler, jobId);
scheduleJobMapper.deleteByPrimaryKey(jobId) ;
}

4、配置一个测试的定时器

4.1 定时接口封装

public interface TaskService {
void run(String params);
}

4.2 测试定时器

@Component("getTimeTask")
public class GetTimeTask implements TaskService {
private static final Logger LOG = LoggerFactory.getLogger(GetTimeTask.class.getName()) ;
private static final SimpleDateFormat format =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
@Override
public void run(String params) {
LOG.info("Params === >> " + params);
LOG.info("当前时间::::"+format.format(new Date()));
}
}

(六)整合 QuartJob ,实现定时器实时管理的更多相关文章

  1. SpringBoot2.0 整合 QuartJob ,实现定时器实时管理

    一.QuartJob简介 1.一句话描述 Quartz是一个完全由java编写的开源作业调度框架,形式简易,功能强大. 2.核心API (1).Scheduler 代表一个 Quartz 的独立运行容 ...

  2. (六)boost库之内存管理shared_ptr

    (六)boost库之内存管理shared_ptr 1.shared_ptr的基本用法 boost::shared_ptr<int> sp(new int(10)); //一个指向整数的sh ...

  3. Shiro 整合SpringMVC 并实现权限管理,登录和注销

    Shiro 整合SpringMVC 并且实现权限管理,登录和注销 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring S ...

  4. Linux第六周学习总结——进程额管理和进程的创建

    Linux第六周学习总结--进程额管理和进程的创建 作者:刘浩晨 [原创作品转载请注明出处] <Linux内核分析>MOOC课程http://mooc.study.163.com/cour ...

  5. 使用spring整合Quartz实现—定时器

    使用spring整合Quartz实现—定时器(Maven项目做演示) 不基于特定的基类的方法 一,开发环境以及依赖的jar包 Spring 4.2.6.RELEASE Maven 3.3.9 Jdk ...

  6. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  7. SpringBoot非官方教程 | 第二十六篇: sprinboot整合elk,搭建实时日志平台

    转载请标明出处: 原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/sprinboot25-elk/ 本文出自方志朋的博客 这篇文章主要介绍 ...

  8. springBoot整合spring security实现权限管理(单体应用版)--筑基初期

    写在前面 在前面的学习当中,我们对spring security有了一个小小的认识,接下来我们整合目前的主流框架springBoot,实现权限的管理. 在这之前,假定你已经了解了基于资源的权限管理模型 ...

  9. (stm32f103学习总结)—RTC独立定时器—实时时钟实验

    一.STM32F1 RTC介绍 1.1 RTC简介 STM32 的实时时钟( RTC)是一个独立的定时器. STM32 的 RTC 模 块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的 ...

随机推荐

  1. 使用mybatis执行对应的SQL Mapper配置中的insert、update、delete等标签操作,数据库记录不变

    我使用springMVC集成mybatis,执行SQLMapper配置文件里的insert操作,发现程序没有报错,但数据库表里却没有刚才插入的记录.查了很多资料,终于在一篇博客上找到了答案:在执行完方 ...

  2. 解决threadLocal父子变量传递问题

    一.问题的提出 在系统开发过程中常使用ThreadLocal进行传递日志的RequestId,由此来获取整条请求链路.然而当线程中开启了其他的线程,此时ThreadLocal里面的数据将会出现无法获取 ...

  3. mysql8.0.19压缩版安装

    1.官网下载.zip格式的MySQL Server的压缩包,选择x86或x64版,并解压. 2. 创建 data文件夹 及 my.ini文件,并编辑 [mysqld] # 设置为自己MYSQL的安装目 ...

  4. sql删除重复数据思路

    总的思路就是先找出表中重复数据中的一条数据,插入临时表中,删除所有的重复数据,然后再将临时表中的数据插入表中.所以重点是如何找出重复数据中的一条数据,有三种情况 1.重复数据完全一样,使用distin ...

  5. EF Core CodeFirst数据库自动迁移

    开发过程中都会遇到数据库数据结构更新的问题,怎么对数据库更新进行版本控制呢? 不同的项目对数据库版本更新控制的方式不同,常用的有第三方Evolve,开发人员将数据库更新脚本按照版本号的放在一起,然后执 ...

  6. Java并发包源码学习系列:ReentrantLock可重入独占锁详解

    目录 基本用法介绍 继承体系 构造方法 state状态表示 获取锁 void lock()方法 NonfairSync FairSync 公平与非公平策略的差异 void lockInterrupti ...

  7. Supervisord进程管家

    Supervisord进程管家 Supervisord是一个守护进程的工具,当进程意外终止或服务器掉电起来后,希望进程能够自动运行,supervisord可以很好的为我们做这件事情.同时supervi ...

  8. Spark内核解析

    Spark内核概述 Spark内核泛指Spark的核心运行机制,包括Spark核心组件的运行机制.Spark任务调度机制.Spark内存管理机制.Spark核心功能的运行原理等,熟练掌握Spark内核 ...

  9. 【Java基础】Java8 新特性

    Java8 新特性 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).使用它可以写出更简洁.更灵活的代码. L ...

  10. 【JavaWeb】Servlet 程序

    Servlet 程序 Servlet Servlet 是在 Web 服务器中运行的小型 Java 程序.Servlet 通常通过 HTTP(超文本传输​​协议)接收和响应来自 Web 客户端的请求. ...