Quartz 简介
Quartz是一个完全由java编写的开源作业调度框架。
简单来说,就是可以帮助我们设置一个有规律的或者在某个具体点干点想干的事的一个开源框架。
它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表。Jobs可以做成标准的Java组件或 EJBs。
Quartz是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。
Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能。这些功能的主要接口(API)是Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。
1.1 quartz的特点
1.quartz能嵌入到任何独立的系统中运行
2.quartz能在应用服务器或者servlet容器中实例化,并且能够参与XA事物
3.quartz能够以独立的方式运行(在它自己的Java虚拟机中),可以通过RMI使用quartz
1.2 quartz的应用背景
凡是业务中有需要用到定时的功能,都可以考虑用到quartz
1.3 quartz和spring自带的定时器Timer Task的比较
精确度和功能 :
Quartz可以通过cron表达式精确到特定时间执行,而TimerTask不能。
Quartz拥有TimerTask所有的功能,而TimerTask则没有。
任务类的数量 :
Quartz每次执行都创建一个新的任务类对象。
TimerTask则每次使用同一个任务类对象。
对异常的处理 :
Quartz的某次执行任务过程中抛出异常,不影响下一次任务的执行,当下一次执行时间到来时,定时器会再次执行任务。
quartz调度核心元素:
Scheduler:任务调度器,是实际执行任务调度的控制器。在spring中通过SchedulerFactoryBean封装起来。
Trigger:触发器,用于定义任务调度的时间规则,有SimpleTrigger,CronTrigger,DateIntervalTrigger和NthIncludedDayTrigger,其中CronTrigger用的比较多,本文主要介绍这种方式。CronTrigger在spring中封装在CronTriggerFactoryBean中。
Calendar:它是一些日历特定时间点的集合。一个trigger可以包含多个Calendar,以便排除或包含某些时间点。
JobDetail:用来描述Job实现类及其它相关的静态信息,如Job名字、关联监听器等信息。在spring中有JobDetailFactoryBean和 MethodInvokingJobDetailFactoryBean两种实现,如果任务调度只需要执行某个类的某个方法,就可以通过MethodInvokingJobDetailFactoryBean来调用。
Job:是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中。实现Job接口的任务,默认是无状态的,若要将Job设置成有状态的,在quartz中是给实现的Job添加@DisallowConcurrentExecution注解(以前是实现StatefulJob接口,现在已被Deprecated),在与spring结合中可以在spring配置文件的job detail中配置concurrent参数。
用法
废话不多说,下面就是具体的使用方式。
第一步 引入jar包
首先我们要引入jar包
用quartz,我们仅仅需要在maven的pom文件中添加依赖即可。我使用的是现在最新的一个版本2.3.0,大家可以在maven的仓库获取到最新的版本依赖,地址:http://mvnrepository.com/artifact/org.quartz-scheduler/quartz
但然也可以使用这个2.3.0的依赖,下面的例子都是使用此依赖并实现了效果。
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
第二步 属性文件
quartz使用名为quartz.properties的配置文件。刚开始时该配置文件不是必须的,但是为了使用最基本的配置,该文件必须位于classpath下。
如果你准备构建一个使用quartz的web应用(以.war包的形式),你应该将quartz.properties文件放到WEB-INF/classes目录下。
当然,springboot项目放在resource目录下就好了
# 固定前缀org.quartz
# 主要分为scheduler、threadPool、jobStore、plugin等部分
#
#
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
org.quartz.scheduler.instanceIdGenerator.class = org.quartz.simpl.SimpleInstanceIdGenerator
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.scheduler.wrapJobExecutionInUserTransaction=false
# 实例化ThreadPool时,使用的线程类为SimpleThreadPool
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
# threadCount和threadPriority将以setter的形式注入ThreadPool实例
# 并发个数
org.quartz.threadPool.threadCount=5
# 优先级
org.quartz.threadPool.threadPriority=5
#数据保存方式 持久化到数据库
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库平台 mysql
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#表的前缀
org.quartz.jobStore.tablePrefix = QRTZ_
#数据库别名 spring配置数据源 则这里配置的数据源不起作用 在spring中指定quartz的数据源
org.quartz.jobStore.dataSource = clusterDS
# ------------------------使用常规数据源配置
# 数据库驱动
org.quartz.dataSource.clusterDS.driver = com.mysql.jdbc.Driver
# 数据库连接地址
org.quartz.dataSource.clusterDS.URL = jdbc:mysql:/host:port/db_table?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
# 数据库用户名
org.quartz.dataSource.clusterDS.user = root
# 数据库密码
org.quartz.dataSource.clusterDS.password = xxxxxx
org.quartz.dataSource.clusterDS.maxConnections = 4
## ------------------------使用JDBCJobStore配置
#
## 所有的quartz数据例如job和Trigger的细节信息被保存在内存或数据库中,有两种实现:JobStoreTX(自己管理事务)和JobStoreCMT(application server管理事务,即全局事务JTA)
#
#org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
## 最大能忍受的触发超时时间(触发器被认定为“misfired”之前),如果超过则认为“失误”【默认60秒】
#
#org.quartz.jobStore.misfireThreshold = 5000
#
## 类似于Hibernate的dialect,用于处理DB之间的差异,StdJDBCDelegate能满足大部分的DB
#
#org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
## 配置数据源的名称,在后面配置数据源的时候要用到,例如org.quartz.dataSource.clusterDS.driver = com.mysql.jdbc.Driver
#
#org.quartz.jobStore.dataSource = clusterDS
#
## 数据表前缀
#
#org.quartz.jobStore.tablePrefix = QRTZ_
#
## 为了指示JDBCJobStore所有的JobDataMaps中的值都是字符串,并且能以“名字-值”对的方式存储而不是以复杂对象的序列化形式存储在BLOB字段中,应该设置为true(缺省方式)
#
org.quartz.jobStore.useProperties = true
#
## 是否集群、负载均衡、容错,如果应用在集群中设置为false会出错
#
org.quartz.jobStore.isClustered = true
#
## 检入到数据库中的频率(毫秒)。检查是否其他的实例到了应当检入的时候未检入这能指出一个失败的实例,且当前Scheduler会以此来接管执行失败并可恢复的Job通过检入操作,Scheduler也会更新自身的状态记录
org.quartz.jobStore.clusterCheckinInterval = 20000
#
## jobStore处理未按时触发的Job的数量
#
##org.quartz.jobStore.maxMisfiresToHandleAtATime = 20
#
## true/false,true则调用connection的setAutoCommit(false)方法
#
##org.quartz.jobStore.dontSetAutoCommitFalse = true
#
## 加锁的SQL语句,默认为SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
#
## {0}=$@org.quartz.jobStore.tablePrefix
#
##org.quartz.jobStore.selectWithLockSQL = false
#
## true/false, true则调用connection的setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE) 方法
#
##org.quartz.jobStore.txIsolationLevelSerializable = false
#
## 触发job时是否需要拥有锁
#
org.quartz.jobStore.acquireTriggersWithinLock = true
#
下面是springboot的配置类
import java.io.IOException;
import java.util.Properties;
import org.quartz.Scheduler;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
@Configuration
public class QuartzConfigure {
// @Autowired
// private DataSource dataSource;
@Bean(name="SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// factory.setDataSource(dataSource);
factory.setQuartzProperties(quartzProperties());
factory.setStartupDelay(15);
return factory;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
//在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
/*
* quartz初始化监听器
*/
@Bean
public QuartzInitializerListener executorListener() {
return new QuartzInitializerListener();
}
/*
* 通过SchedulerFactoryBean获取Scheduler的实例
*/
@Bean(name="Scheduler")
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
}
这份配置是我自己整理的,大家在使用时需要修改数据库的连接,可能有人回问了,我们一般项目都会有数据库连接的配置,我这个quartz使用我配置好的database可以么?
以我目前的研究来看,不行,细心的观众朋友可能已经看到了,我的配置类里注释掉了database。一开始我是想用spring依赖注入来配置database,但是都不能行事。研究了一阵子发现好像是quartz在初始化,用此种依赖注入方式注入进来的database对象时错误的。而且网上也么找到使用非quartz数据库连接的例子。好在quartz不需要占用太多连接。
还有就是数据库表了
#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS
(
SCHED_NAME VARCHAR(80) NOT NULL,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_GROUP VARCHAR(100) NOT NULL,
DESCRIPTION VARCHAR(100) NULL,
JOB_CLASS_NAME VARCHAR(100) 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)
);
CREATE TABLE QRTZ_TRIGGERS
(
SCHED_NAME VARCHAR(80) NOT NULL,
TRIGGER_NAME VARCHAR(100) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_GROUP VARCHAR(100) NOT NULL,
DESCRIPTION VARCHAR(100) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(100) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_SIMPLE_TRIGGERS
(
SCHED_NAME VARCHAR(80) NOT NULL,
TRIGGER_NAME VARCHAR(100) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CRON_TRIGGERS
(
SCHED_NAME VARCHAR(80) NOT NULL,
TRIGGER_NAME VARCHAR(100) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
CRON_EXPRESSION VARCHAR(100) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(80) NOT NULL,
TRIGGER_NAME VARCHAR(100) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
STR_PROP_1 VARCHAR(120) NULL,
STR_PROP_2 VARCHAR(120) NULL,
STR_PROP_3 VARCHAR(120) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_BLOB_TRIGGERS
(
SCHED_NAME VARCHAR(80) NOT NULL,
TRIGGER_NAME VARCHAR(100) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CALENDARS
(
SCHED_NAME VARCHAR(80) NOT NULL,
CALENDAR_NAME VARCHAR(100) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
SCHED_NAME VARCHAR(80) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
SCHED_NAME VARCHAR(80) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(100) NOT NULL,
TRIGGER_GROUP VARCHAR(100) NOT NULL,
INSTANCE_NAME VARCHAR(100) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(100) NULL,
JOB_GROUP VARCHAR(100) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE QRTZ_SCHEDULER_STATE
(
SCHED_NAME VARCHAR(80) NOT NULL,
INSTANCE_NAME VARCHAR(100) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE QRTZ_LOCKS
(
SCHED_NAME VARCHAR(80) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
commit;
到这里我们的quartz配置就完成了,下面我们就开始Job
第三步 创建定时任务类
下面我就创建定时任务类,需要继承org.quartz.Job类
import com.lenovo.lmp.common.util.SpringUtil;
import com.lenovo.lmp.outbound.service.WmsPickIngSchedule;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyJob implements Job {
private static final Logger logger = LoggerFactory.getLogger(MyJob.class);
/**
* 核心方法,Quartz Job真正的执行逻辑.
* @param context 中封装有Quartz运行所需要的所有信息
* @throws JobExecutionException execute()方法只允许抛出JobExecutionException异常
*/
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
logger.info("================= MyJob ===============");
String result = "error";
try{
MySchedule mySchedule = SpringUtil.getBean("mySchedule", MySchedule.class);
result = (String) mySchedule.start();
} catch (Exception e) {
e.printStackTrace();
}
logger.info("================= MyJob : " + result);
}
}
我这个Job类没有交给spring管理,所以我用的spring容器通过bean id 来获取我所要用的service。
servce就是我们要执行的业务代码。这样一来我们整个job的编写就完成了。剩下就是启动job了。
第四步 自动
启动我们只需要几部
public void addJob(String jobClassName, String jobGroupName, String cronExpression)throws Exception{
// 启动调度器
scheduler.start();
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).requestRecovery(true).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) {
System.out.println("创建定时任务失败"+e);
throw new Exception("创建定时任务失败");
}
}
我们需要启动调度器,构建job,构建表达式,在通过调度器启动job,具体代码如上。
但是大家可能觉着这样代码太死,不方便,我这里可以给大家一个controller
增删改查都有
import com.alibaba.fastjson.JSONObject;
import com.lenovo.lmp.common.model.JobAndTrigger;
import com.lenovo.lmp.common.service.IJobAndTriggerService;
import com.lenovo.lmp.common.util.SpringUtil;
import com.lenovo.mstool.client.auth.provider.IgnoreServiceAuth;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import com.github.pagehelper.PageInfo;
@RestController
@RequestMapping(value="/job")
public class JobController
{
@Autowired
private IJobAndTriggerService iJobAndTriggerService;
//加入Qulifier注解,通过名称注入bean
@Autowired @Qualifier("Scheduler")
private Scheduler scheduler;
private static Logger log = LoggerFactory.getLogger(JobController.class);
@PostMapping(value="/addjob")
@ResponseBody
public void addjob(@RequestBody String context) throws Exception
{
JSONObject json = JSONObject.parseObject(context);
String jobClassName = json.getString("jobClassName");
String jobGroupName = json.getString("jobGroupName");
String cronExpression = json.getString("cronExpression");
addJob(jobClassName, jobGroupName, cronExpression);
}
public void addJob(String jobClassName, String jobGroupName, String cronExpression)throws Exception{
// 启动调度器
scheduler.start();
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).requestRecovery(true).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) {
System.out.println("创建定时任务失败"+e);
throw new Exception("创建定时任务失败");
}
}
@PostMapping(value="/pausejob")
@ResponseBody
public void pausejob(@RequestBody String context) throws Exception
{
JSONObject json = JSONObject.parseObject(context);
String jobClassName = json.getString("jobClassName");
String jobGroupName = json.getString("jobGroupName");
jobPause(jobClassName, jobGroupName);
}
public void jobPause(String jobClassName, String jobGroupName) throws Exception
{
scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
}
@PostMapping(value="/resumejob")
@ResponseBody
public void resumejob(@RequestBody String context) throws Exception
{
JSONObject json = JSONObject.parseObject(context);
String jobClassName = json.getString("jobClassName");
String jobGroupName = json.getString("jobGroupName");
jobresume(jobClassName, jobGroupName);
}
public void jobresume(String jobClassName, String jobGroupName) throws Exception
{
scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
}
@PostMapping(value="/reschedulejob")
@ResponseBody
public void rescheduleJob(@RequestBody String context) throws Exception
{
JSONObject json = JSONObject.parseObject(context);
String jobClassName = json.getString("jobClassName");
String jobGroupName = json.getString("jobGroupName");
String cronExpression = json.getString("cronExpression");
jobreschedule(jobClassName, jobGroupName, cronExpression);
}
public void jobreschedule(String jobClassName, String jobGroupName, String cronExpression) throws Exception
{
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
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) {
System.out.println("更新定时任务失败"+e);
throw new Exception("更新定时任务失败");
}
}
@PostMapping(value="/deletejob")
@ResponseBody
public void deletejob(@RequestBody String context) throws Exception
{
JSONObject json = JSONObject.parseObject(context);
String jobClassName = json.getString("jobClassName");
String jobGroupName = json.getString("jobGroupName");
jobdelete(jobClassName, jobGroupName);
}
public void jobdelete(String jobClassName, String jobGroupName) throws Exception
{
scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
}
@PostMapping(value="/queryjob")
@ResponseBody
public Object queryjob(@RequestParam(value="pageNum")Integer pageNum, @RequestParam(value="pageSize")Integer pageSize)
{
PageInfo<JobAndTrigger> jobAndTrigger = iJobAndTriggerService.getJobAndTriggerDetails(pageNum, pageSize);
JSONObject map = new JSONObject();
map.put("JobAndTrigger", jobAndTrigger);
map.put("number", jobAndTrigger.getTotal());
return map;
}
public static Job getClass(String classname) throws Exception
{
Class<?> class1 = Class.forName(classname);
return (Job)class1.newInstance();
}
}
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.plugins.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lenovo.common.util.Convert;
import com.lenovo.lmp.common.dao.JobAndTriggerMapper;
import com.lenovo.lmp.common.model.JobAndTrigger;
import com.lenovo.lmp.common.service.IJobAndTriggerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class JobAndTriggerImpl implements IJobAndTriggerService {
@Autowired
private JobAndTriggerMapper jobAndTriggerMapper;
public PageInfo<JobAndTrigger> getJobAndTriggerDetails(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<JobAndTrigger> list = jobAndTriggerMapper.getJobAndTriggerDetails();
PageInfo<JobAndTrigger> page = new PageInfo<JobAndTrigger>(list);
return page;
}
}
import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.lenovo.lmp.common.model.JobAndTrigger;
public interface JobAndTriggerMapper {
@Select(" <script> SELECT " +
"QRTZ_JOB_DETAILS.JOB_NAME," +
"QRTZ_JOB_DETAILS.JOB_GROUP," +
"QRTZ_JOB_DETAILS.JOB_CLASS_NAME," +
"QRTZ_TRIGGERS.TRIGGER_NAME," +
"QRTZ_TRIGGERS.TRIGGER_GROUP," +
"QRTZ_CRON_TRIGGERS.CRON_EXPRESSION," +
"QRTZ_CRON_TRIGGERS.TIME_ZONE_ID" +
" FROM " +
"QRTZ_JOB_DETAILS" +
" JOIN QRTZ_TRIGGERS" +
" JOIN QRTZ_CRON_TRIGGERS ON QRTZ_JOB_DETAILS.JOB_NAME = QRTZ_TRIGGERS.JOB_NAME" +
" AND QRTZ_TRIGGERS.TRIGGER_NAME = QRTZ_CRON_TRIGGERS.TRIGGER_NAME" +
" AND QRTZ_TRIGGERS.TRIGGER_GROUP = QRTZ_CRON_TRIGGERS.TRIGGER_GROUP </script>")
List<JobAndTrigger> getJobAndTriggerDetails();
}
以上就是Query使用指南的全部内容,当然使用过程中还是有一些问题需要注意
- 定时任务时间设置的不要太短,有几率服务器卡顿导致上一个任务没跑完,下一个任务就触发了,会有问题。一般来说这个quartz配置是分布式的,多个服务器只要在一个数据库下就只会有一个定时任务再跑。到点就会跑,所以时间太短会导致有几率同时两个job在运行。
2.如果没有job,可能会有数据库连接中断异常抛出,但是没关系,我们用的mysql,如果长时间没有信息传递mysql会中断连接,导致服务器异常,我们在配置里有连接中断重新连接的配置,所以不用担心。如果设置数据库连接属性也会解决此问题,但是会导致不安全,不建议更改数据库设置。