自动化定时任务 分布式集成[集群] 定时自动漂移
前言
当你使用分布式系统时候,往往会使用集群,但是在集群模式中定时任务部署会遇到,俩个部署运行一个定时,这样就出现了数据安全性问题[数据插入多条记录,数据库死锁,数据不全等]
为了解决此问题,有俩种实现方案,一种使用Quartz组件集成自己项目,第二种就是使用开源框架xxljob等
这里我们介绍使用Quartz方式实现分布式自动化定时任务,这个非但可以实现定时执行任务,也可以随时调用一个业务层函数.哈哈.是不是很神奇
原理,Quartz默认是使用内存进行的任务调度,这样就使得集群不能共享一个资源,出现问题了.然后我们可以有俩种方式应对,1.redis[缓存数据库],2.数据库.
这里我们使用数据库方式进行,因为官方提供的嘛.比较好用,不然你还需要实现一个redis的调度类去做,很麻烦.
ok上代码…
定时控制类Controller层
crud+恢复+暂停+移除定时的操作
package com.techhero.base.system.controller.abs;
import com.techhero.base.system.service.abs.QuartzService;
import com.techhero.common.base.BaseController;
import com.techhero.common.model.abs.QuartzControl;
import com.techhero.common.utils.req.ResBean;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/quartzMng")
public class QuartzController extends BaseController {
@Resource
private QuartzService quartzService;
/*添加任务*/
@PostMapping
public ResBean addJob(@RequestBody QuartzControl quartzControl) {
return quartzService.addJob(quartzControl);
}
/*获取任务列表*/
@PostMapping("findListPage")
public ResBean findListPage(@RequestBody QuartzControl quartzControl) {
return quartzService.findListPage(quartzControl);
}
/*删除任务*/
@DeleteMapping("{id}")
public ResBean delJob(@PathVariable String id) {
return quartzService.delJob(id);
}
/*修改任务*/
@PutMapping
public ResBean updateJob(@RequestBody QuartzControl quartzControl){
return quartzService.updateJob(quartzControl);
}
/*启动任务*/
@GetMapping("startJob/{id}")
public ResBean startJob(@PathVariable String id){
return quartzService.startJob(id);
}
/*暂停任务*/
@GetMapping("pauseJob/{id}")
public ResBean pauseJob(@PathVariable String id){
return quartzService.pauseJob(id);
}
/*恢复任务*/
@GetMapping("resumeJob/{id}")
public ResBean resumeJob(@PathVariable String id){
return quartzService.resumeJob(id);
}
}
业务层
接口
package com.techhero.base.system.service.abs;
import com.techhero.common.model.abs.QuartzControl;
import com.techhero.common.utils.req.ResBean;
/*分布式石英任务管理*/
public interface QuartzService {
/*添加*/
ResBean addJob(QuartzControl quartzControl);
/*查询*/
ResBean findListPage(QuartzControl quartzControl);
/*修改*/
ResBean updateJob(QuartzControl quartzControl);
/*删除*/
ResBean delJob(String id);
/*启动任务*/
ResBean startJob(String id);
/*暂停任务*/
ResBean pauseJob(String id);
/*恢复任务*/
ResBean resumeJob(String id);
}
实现类
package com.techhero.base.system.service.abs.impl;
import com.github.pagehelper.PageInfo;
import com.techhero.base.system.mapper.abs.QuartzControlMapper;
import com.techhero.base.system.service.abs.QuartzDispatchService;
import com.techhero.base.system.service.abs.QuartzService;
import com.techhero.common.model.abs.QuartzControl;
import com.techhero.common.utils.req.ResBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
@Slf4j
public class QuartzServiceImpl implements QuartzService {
@Resource
private QuartzControlMapper quartzControlMapper;
@Resource
private QuartzDispatchService quartzDispatchService;
/*添加任务*/
@Override
public ResBean addJob(QuartzControl quartzControl) {
log.info("任务添加\n{}",quartzControl);
/*默认为子系统未启动状态*/
quartzControl.setJobState(0);
int i = quartzControlMapper.insertSelective(quartzControl);
log.info("任务添加完成....\n{}",quartzControl);
return ResBean.addValid(i);
}
/*查询任务列表*/
@Override
public ResBean findListPage(QuartzControl quartzControl) {
quartzControl.startPage();
List<QuartzControl> quartzControls = this.quartzControlMapper.selectAll();
return ResBean.success(new PageInfo<QuartzControl>(quartzControls));
}
/*修改任务*/
@Override
public ResBean updateJob(QuartzControl quartzControl) {
/*先查询到原始的任务信息,将原始任务在子系统删除*/
String id = quartzControl.getId();
QuartzControl oldQuartzControl= quartzControlMapper.selectByPrimaryKey(id);
quartzDispatchService.removeJob(oldQuartzControl);
if(oldQuartzControl.getJobState().equals(1)){
quartzControl.setJobState(1);
/*当原始任务已经启动情况下*/
String jobAddress = quartzDispatchService.updateJob(quartzControl);
if (StringUtils.isNotBlank(jobAddress)) {
quartzControl.setJobAddress(jobAddress);
}
}else{
/*其他状态修改为*/
quartzControl.setJobState(0);
quartzControl.setJobAddress(null);
}
/*更新定时表数据*/
int i = quartzControlMapper.updateByPrimaryKeySelective(quartzControl);
return ResBean.addValid(i);
}
/*删除任务*/
@Override
public ResBean delJob(String id) {
QuartzControl quartzControl = quartzControlMapper.selectByPrimaryKey(id);
quartzDispatchService.removeJob(quartzControl);
int i = quartzControlMapper.deleteByPrimaryKey(id);
return ResBean.validCountBean(i);
}
/*启动任务*/
@Override
public ResBean startJob(String id) {
QuartzControl quartzControl = quartzControlMapper.selectByPrimaryKey(id);
String jobAddress = quartzDispatchService.startJob(quartzControl);
int jobState=1;
if(quartzControl.getJobType().equals(0)){
jobState=0;
}
int i = quartzControlMapper.updateByPrimaryKeySelective(QuartzControl.builder().id(id).jobAddress(jobAddress).jobState(jobState).build());
log.info("任务启动成功");
return ResBean.validCountBean(i);
}
/*暂停任务*/
@Override
public ResBean pauseJob(String id) {
QuartzControl quartzControl = quartzControlMapper.selectByPrimaryKey(id);
quartzDispatchService.pauseJob(quartzControl);
int i = quartzControlMapper.updateByPrimaryKeySelective(QuartzControl.builder().id(id).jobState(2).build());
log.info("任务暂停成功");
return ResBean.validCountBean(i);
}
/*恢复任务*/
@Override
public ResBean resumeJob(String id) {
QuartzControl quartzControl = quartzControlMapper.selectByPrimaryKey(id);
quartzDispatchService.resumeJob(quartzControl);
int i = quartzControlMapper.updateByPrimaryKeySelective(QuartzControl.builder().id(id).jobState(1).build());
log.info("任务恢复成功");
return ResBean.validCountBean(i);
}
}
任务调度类–由于有可能你的系统有很多子系统
所以这里专门做任务调度
接口
package com.techhero.base.system.service.abs;
import com.techhero.common.model.abs.QuartzControl;
/*任务调度service*/
public interface QuartzDispatchService {
/*启动任务*/
String startJob(QuartzControl quartzControl);
/*移除任务*/
void removeJob(QuartzControl quartzControl);
/*修改任务*/
String updateJob(QuartzControl quartzControl);
/*暂停任务*/
void pauseJob(QuartzControl quartzControl);
/*恢复任务*/
void resumeJob(QuartzControl quartzControl);
}
实现
package com.techhero.base.system.service.abs.impl;
import com.techhero.base.system.feigin.abs.TransDataQuartzDispatchFeign;
import com.techhero.base.system.service.abs.QuartzDispatchService;
import com.techhero.common.constant.ServiceNameConstant;
import com.techhero.common.model.abs.QuartzControl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
@Slf4j
public class QuartzDispatchServiceImpl implements QuartzDispatchService {
@Resource
private TransDataQuartzDispatchFeign transDataQuartzDispatchFeign;
/*启动一个任务*/
@Override
public String startJob(QuartzControl quartzControl) {
/*服务名:代表那个子系统[这个字段保存微服务名称]*/
String serverName = quartzControl.getJobGroup();
if(StringUtils.isNotBlank(serverName)){
if(serverName.equals(ServiceNameConstant.TRANSDATA_SERVICE)){
return transDataQuartzDispatchFeign.addAndStartJob(quartzControl);
}
}
log.info("服务名称没有指定\n{}",quartzControl);
return null;
}
/*删除一个任务*/
@Override
public void removeJob(QuartzControl quartzControl) {
/*服务名:代表那个子系统[这个字段保存微服务名称]*/
String serverName = quartzControl.getJobGroup();
if(StringUtils.isNotBlank(serverName)){
if(serverName.equals(ServiceNameConstant.TRANSDATA_SERVICE)){
transDataQuartzDispatchFeign.removeJob(quartzControl);
}
return ;
}
log.info("服务名称没有指定\n{}",quartzControl);
}
/*修改任务*/
@Override
public String updateJob(QuartzControl quartzControl) {
/*服务名:代表那个子系统[这个字段保存微服务名称]*/
String serverName = quartzControl.getJobGroup();
if(StringUtils.isNotBlank(serverName)){
if(serverName.equals(ServiceNameConstant.TRANSDATA_SERVICE)){
Integer jobState = quartzControl.getJobState();
if(jobState==2){
/*子系统如果是暂停状态,则将此定时清除,后边需要人工启动这个定时*/
transDataQuartzDispatchFeign.removeJob(quartzControl);
}else if(jobState==1){
/*子系统如果是启动状态,则之间调用修改*/
return transDataQuartzDispatchFeign.updateJob(quartzControl);
}
}
}
log.info("服务名称没有指定\n{}",quartzControl);
return null;
}
/*暂停任务*/
@Override
public void pauseJob(QuartzControl quartzControl) {
/*服务名:代表那个子系统[这个字段保存微服务名称]*/
String serverName = quartzControl.getJobGroup();
if(StringUtils.isNotBlank(serverName)){
if(serverName.equals(ServiceNameConstant.TRANSDATA_SERVICE)){
Integer jobState = quartzControl.getJobState();
if(jobState==1){
/*只有在任务启动状态下时候才能暂停任务*/
transDataQuartzDispatchFeign.pauseJob(quartzControl);
}
}
}
}
/*恢复任务*/
@Override
public void resumeJob(QuartzControl quartzControl) {
/*服务名:代表那个子系统[这个字段保存微服务名称]*/
String serverName = quartzControl.getJobGroup();
if(StringUtils.isNotBlank(serverName)){
if(serverName.equals(ServiceNameConstant.TRANSDATA_SERVICE)){
Integer jobState = quartzControl.getJobState();
if(jobState==2){
/*只有在任务启动状态下时候才能暂停任务*/
transDataQuartzDispatchFeign.resumeJob(quartzControl);
}
}
}
}
}
OK以上内容比较简单,其实就是做了一个定时任务的记录表crud 和远程调用子系统,让子系统执行一个定时任务
下边上集成时候的和一些核心类
实现方案,quartz是可以进行传递参数的,然后我们将service名称,和函数名称作为一个参数传递给子系统,子系统通过反射进行调用就行,所以没有必要所有类都实现JOB接口.只需要定义一个就行.
配置quartz 配置类
package com.techhero.common.bean.config.quartz;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import javax.sql.DataSource;
import java.util.Properties;
/**
* quartz定时任务配置
*/
@Configuration
@ConditionalOnProperty(value = "task.switch",havingValue = "true")
@EnableScheduling
public class QuartzConfiguration {
/**
* 继承org.springframework.scheduling.quartz.SpringBeanJobFactory
* 实现任务实例化方式
*
* 可以看到上面配置类中,AutowiringSpringBeanJobFactory我们继承了SpringBeanJobFactory类
* 并且通过实现ApplicationContextAware接口获取ApplicationContext设置方法
* 通过外部实例化时设置ApplicationContext实例对象,在createJobInstance方法内
* 我们采用AutowireCapableBeanFactory来托管SpringBeanJobFactory类中createJobInstance方法返回的定时任务实例
* 这样就可以在定时任务类内使用Spring Ioc相关的注解进行注入业务逻辑实例。
*/
public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
/**
* 将job实例交给spring ioc托管
* 我们在job实例实现类内可以直接使用spring注入的调用被spring ioc管理的实例
*/
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
/**
* 将job实例交付给spring ioc
*/
beanFactory.autowireBean(job);
return job;
}
}
/**
* 配置任务工厂实例
*
* 任务工厂是在本章配置调度器时所需要的实例,我们通过jobFactory方法注入ApplicationContext实例
* 来创建一个AutowiringSpringBeanJobFactory对象,并且将对象实例托管到Spring Ioc容器内。
*/
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
/**
* 采用自定义任务工厂 整合spring实例来完成构建任务
* see {@link AutowiringSpringBeanJobFactory}
*/
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
/**
* 配置任务调度器
* 使用项目数据源作为quartz数据源
*
* 在上面配置类中可以看到方法schedulerFactoryBean内自动注入了JobFactory实例,
* 也就是我们自定义的AutowiringSpringBeanJobFactory任务工厂实例,
* 调用SchedulerFactoryBean对象的setConfigLocation方法来设置quartz定时任务框架的基本配置
*
* @param jobFactory 自定义配置任务工厂
* @param dataSource 数据源实例
* @return SchedulerFactoryBean
* @throws Exception
*/
@Bean(destroyMethod = "destroy", autowire = Autowire.NO)
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, DataSource dataSource) throws Exception {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
//将spring管理job自定义工厂交由调度器维护
schedulerFactoryBean.setJobFactory(jobFactory);
//设置覆盖已存在的任务
schedulerFactoryBean.setOverwriteExistingJobs(true);
//项目启动完成后,等待2秒后开始执行调度器初始化
schedulerFactoryBean.setStartupDelay(2);
//设置调度器自动运行
schedulerFactoryBean.setAutoStartup(true);
//设置数据源,使用与项目统一数据源
schedulerFactoryBean.setDataSource(dataSource);
//设置上下文spring bean name
schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");
//设置配置文件位置
//schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));
setQuartzProperties(schedulerFactoryBean);
return schedulerFactoryBean;
}
public void setQuartzProperties(SchedulerFactoryBean schedulerFactoryBean){
Properties prop = new Properties();
/*调度器实例名称*/
prop.put("org.quartz.scheduler.instanceName","quartzScheduler");
/*调度器实例编号自动生成*/
prop.put("org.quartz.scheduler.instanceId","AUTO");
/*持久化方式配置*/
prop.put("org.quartz.jobStore.class","org.quartz.impl.jdbcjobstore.JobStoreTX");
/*持久化方式配置数据驱动,ORACLE数据库*/
prop.put("org.quartz.jobStore.driverDelegateClass","org.quartz.impl.jdbcjobstore.oracle.OracleDelegate");
/*quartz相关数据表前缀名*/
prop.put("org.quartz.jobStore.tablePrefix","QRTZ_");
/*开启分布式部署*/
prop.put("org.quartz.jobStore.isClustered","true");
/*配置是否使用*/
prop.put("org.quartz.jobStore.useProperties","false");
/*分布式节点有效性检查时间间隔,单位:毫秒*/
prop.put("org.quartz.jobStore.clusterCheckinInterval","20000");
/*线程池实现类*/
prop.put("org.quartz.threadPool.class","org.quartz.simpl.SimpleThreadPool");
/*执行最大并发线程数量*/
prop.put("org.quartz.threadPool.threadCount","20");
/*线程优先级 不能大于9*/
prop.put("org.quartz.threadPool.threadPriority","9");
/*配置是否启动自动加载数据库内的定时任务*/
prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread","true");
/*ID生成器*/
/*prop.put("org.quartz.scheduler.instanceIdGenerator.class","org.quartz.simpl.HostnameInstanceIdGenerator");*/
/*配置为守护线程,设置后任务将不会执行*/
/*prop.put("org.quartz.threadPool.makeThreadsDaemons","true");*/
}
}
上边读取配置文件有俩种方式.但是我觉得没有必要作为一个配置文件使用,不然每一个子系统还需要重复造轮子.所以这个配置直接写死就行,但是本人乐于助人,吧配置文件方式也在里面注释的写了一下
配置文件如下-放到resource下就行
匹配 //schedulerFactoryBean.setConfigLocation(new ClassPathResource("/quartz.properties")); 代码打开就行
#调度器实例名称
org.quartz.scheduler.instanceName = quartzScheduler
#调度器实例编号自动生成
org.quartz.scheduler.instanceId = AUTO
#示例ID生成器
#org.quartz.scheduler.instanceIdGenerator.class = org.quartz.simpl.HostnameInstanceIdGenerator
#持久化方式配置
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#持久化方式配置数据驱动,ORACLE数据库
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#quartz相关数据表前缀名
org.quartz.jobStore.tablePrefix = QRTZ_
#开启分布式部署
org.quartz.jobStore.isClustered = true
#配置是否使用
org.quartz.jobStore.useProperties = false
#分布式节点有效性检查时间间隔,单位:毫秒
org.quartz.jobStore.clusterCheckinInterval = 20000
#线程池实现类
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#执行最大并发线程数量
org.quartz.threadPool.threadCount = 20
#线程优先级 不能大于9
org.quartz.threadPool.threadPriority = 9
#配置为守护线程,设置后任务将不会执行
#org.quartz.threadPool.makeThreadsDaemons=true
#配置是否启动自动加载数据库内的定时任务,默认true
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
子系统 申请定时任务创建删除修改暂停恢复等controller
package com.techhero.common.bean.config.quartz;
import com.techhero.common.model.abs.QuartzControl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
/*定时任务管理器*/
@Slf4j
@RestController
@RequestMapping("/quartz")
@ConditionalOnProperty(value = "task.switch",havingValue = "true")
public class QuartzManager {
@Resource
private Scheduler scheduler;
@Resource
private ApplicationContext applicationContext;
/*服务器启动端口*/
@Value("${server.port}")
private String serverPort;
/*
* 工具函数,获取当前机器的IP地址和端口
* [方便系统管理定时器回填目前执行的地址]
*/
private String getAddress() {
String startAddress = null;
try {
InetAddress ip4 = Inet4Address.getLocalHost();
startAddress = ip4 + ":" + serverPort;
} catch (UnknownHostException e) {
log.error("[获取IP失败,运行异常]", e);
}
return startAddress;
}
/*拼装JobDetail*/
private JobDetail getJobDetail(QuartzControl quartzControl) throws SchedulerException {
/*任务名称*/
String name = quartzControl.getJobName();
/*任务所属分组*/
String group = quartzControl.getJobGroup();
JobDetail jobDetail = scheduler.getJobDetail(new JobKey(name, group));
if(jobDetail==null){
/*任务描述*/
String jobDesc = quartzControl.getJobDesc();
/*创建任务*/
jobDetail = JobBuilder.newJob(LockerQuartzJob.class).withIdentity(name, group).withDescription(jobDesc).build();
/*设定参数*/
jobDetail.getJobDataMap().put("quartzControl", quartzControl);
}
return jobDetail;
}
/*间隔时间执行单位[秒]*/
private Boolean exeIntervalTime(QuartzControl quartzControl) throws SchedulerException {
/*cron表达式*/
String cronExpression = quartzControl.getJobExpression();
if(StringUtils.isBlank(cronExpression)){
log.info("表达式不能为空\n{}",quartzControl);
return false;
}
Integer seconds=0;
try {
seconds=Integer.valueOf(cronExpression);
} catch (NumberFormatException e) {
log.error("[任务表达式异常]\n{}",quartzControl, e);
return false;
}
JobDetail jobDetail = getJobDetail(quartzControl);
Trigger trigger = scheduler.getTrigger(TriggerKey.triggerKey(quartzControl.getJobName(), quartzControl.getJobGroup()));
if(trigger==null){
/*创建任务触发器*/
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzControl.getJobName(), quartzControl.getJobGroup())
.startNow()
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(seconds))
.build();
/*将触发器与任务绑定到调度器内*/
scheduler.scheduleJob(jobDetail, trigger);
}
return true;
}
/*cron表达式执行*/
private Boolean exeCron(QuartzControl quartzControl) throws SchedulerException {
/*cron表达式*/
String cronExpression = quartzControl.getJobExpression();
if(StringUtils.isBlank(cronExpression)){
return false;
}
JobDetail jobDetail = getJobDetail(quartzControl);
Trigger trigger = scheduler.getTrigger(TriggerKey.triggerKey(quartzControl.getJobName(), quartzControl.getJobGroup()));
if(trigger==null){
/*创建任务触发器*/
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzControl.getJobName(), quartzControl.getJobGroup())
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression.trim()))
.build();
/*将触发器与任务绑定到调度器内*/
scheduler.scheduleJob(jobDetail, trigger);
}
return true;
}
/*延时执行一次*/
private Boolean exeOnce(QuartzControl quartzControl) throws SchedulerException {
/*初始化执行时间*/
String jobExpression = quartzControl.getJobExpression();
Long addTime = 10L;
try {
addTime = Long.valueOf(jobExpression);
} catch (NumberFormatException e) {
log.error("[时间设定错误,默认使用10秒作为延时]", e);
return false;
}
long startAtTime = 1000 * addTime;
JobDetail jobDetail = getJobDetail(quartzControl);
Trigger trigger = scheduler.getTrigger(TriggerKey.triggerKey(quartzControl.getJobName(), quartzControl.getJobGroup()));
if(trigger==null){
/*创建任务触发器*/
trigger = TriggerBuilder.newTrigger()
.withIdentity(quartzControl.getJobName(), quartzControl.getJobGroup())
.startAt(new Date(startAtTime))
.build();
/*将触发器与任务绑定到调度器内*/
scheduler.scheduleJob(jobDetail, trigger);
}
return true;
}
/*添加任务*/
@PostMapping("addAndStartJob")
public String addAndStartJob(@RequestBody QuartzControl quartzControl) throws SchedulerException {
log.info("正在添加且启动任务...\n{}",quartzControl);
/*定时器执行方式*/
Integer jobType = quartzControl.getJobType();
Boolean flag=false;
if (jobType == 0) {
/*执行一次*/
flag=exeOnce(quartzControl);
} else if (jobType == 1) {
/*cron表达式执行*/
flag=exeCron(quartzControl);
} else if (jobType == 2) {
/*间隔时间执行单位[秒]*/
flag=exeIntervalTime(quartzControl);
}
if(flag){
String address = getAddress();
log.info("添加且启动任务成功...\n{},{}",address,quartzControl);
return address;
}
return null;
}
/*修改一个任务*/
@PostMapping("updateJob")
public String updateJob(@RequestBody QuartzControl quartzControl) throws SchedulerException{
log.info("正在修改任务...\n{}",quartzControl);
/*所谓修改任务其实就是将任务移除了,然后在新增启动*/
removeJob(quartzControl);
String ipAddress = addAndStartJob(quartzControl);
log.info("修改任务成功...\n{}:{}",ipAddress,quartzControl);
return ipAddress;
}
/*暂停任务*/
@PostMapping("pauseJob")
public void pauseJob(@RequestBody QuartzControl quartzControl) throws SchedulerException {
try {
log.info("正在暂停任务...\n{}",quartzControl);
scheduler.pauseJob(JobKey.jobKey(quartzControl.getJobName(), quartzControl.getJobGroup()));
log.info("完成暂停任务...\n{}",quartzControl);
} catch (SchedulerException e) {
log.error("暂停定时任务失败",e);
}
}
/**
* 恢复任务
* @param quartzControl
* @throws SchedulerException
*/
@PostMapping("resumeJob")
public void resumeJob(@RequestBody QuartzControl quartzControl)throws SchedulerException {
try {
log.info("恢复任务中...\n{}",quartzControl);
scheduler.resumeJob(JobKey.jobKey(quartzControl.getJobName(), quartzControl.getJobGroup()));
log.info("恢复任务完毕...\n{}",quartzControl);
} catch (SchedulerException e) {
log.error("恢复定时任务失败",e);
}
}
/*移除任务*/
@PostMapping("removeJob")
public void removeJob(@RequestBody QuartzControl quartzControl) throws SchedulerException {
try {
log.info("删除任务中...\n{}",quartzControl);
TriggerKey triggerKey = TriggerKey.triggerKey(quartzControl.getJobName(), quartzControl.getJobGroup());
/*停止触发器*/
scheduler.pauseTrigger(triggerKey);
/*移除触发器*/
scheduler.unscheduleJob(triggerKey);
/*删除任务*/
scheduler.deleteJob(JobKey.jobKey(quartzControl.getJobName(), quartzControl.getJobGroup()));
log.info("删除任务完成...\n{}",quartzControl);
} catch (Exception e) {
log.error("移除任务失败",e);
}
}
}
基本的job调度类实现一个接口 QuartzJobBean
package com.techhero.common.bean.config.quartz;
import com.techhero.common.model.abs.QuartzControl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.StopWatch;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@Slf4j
@DisallowConcurrentExecution
public class LockerQuartzJob extends QuartzJobBean {
@Resource
private ApplicationContext applicationContext;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
QuartzControl quartzControl = (QuartzControl) jobDataMap.get("quartzControl");
/*任务名称*/
String name = quartzControl.getJobName();
/*任务描述*/
String description = quartzControl.getJobDesc();
log.info("\n===={}任务执行===", name);
log.info("\n任务描述:{}", description);
/*时间记录*/
StopWatch stopWatch = new StopWatch();
stopWatch.start(name);
/*服务名称*/
String jobServiceName = quartzControl.getJobServiceName();
if(StringUtils.isNotEmpty(jobServiceName)){
jobServiceName=jobServiceName.trim();
if(!Character.isLowerCase(jobServiceName.charAt(0))){
jobServiceName=(new StringBuilder()).append(Character.toLowerCase(jobServiceName.charAt(0))).append(jobServiceName.substring(1)).toString();
}
}
/*函数名称*/
String jobMethodName = quartzControl.getJobMethodName();
Object runBean = applicationContext.getBean(jobServiceName);
if (runBean == null) {
log.error("定时任务定义失败,没有这个对象实例在容器中,[{}]", jobServiceName);
return;
}
try {
Method runMethod = runBean.getClass().getDeclaredMethod(jobMethodName, QuartzControl.class);
/*如果传递参数函数没有找到就查询没有参数的函数*/
if (runMethod == null) {
/*验证原生态函数名称*/
runMethod = runBean.getClass().getDeclaredMethod(jobMethodName);
}
if(runMethod == null){
/*如果原生态函数名称没有找到-就加入尾缀Impl试试带参数函数*/
runMethod = runBean.getClass().getDeclaredMethod(jobMethodName+"Impl", QuartzControl.class);
}
if(runMethod == null){
/*如果原生态函数名称没有找到-就加入尾缀Impl试试*/
runMethod = runBean.getClass().getDeclaredMethod(jobMethodName+"Impl");
}
/*必须是公共函数*/
if (runMethod != null && Modifier.isPublic(runMethod.getModifiers())) {
runMethod.invoke(runBean, quartzControl);
stopWatch.stop();
log.info("定时任务执行完毕,消耗时间[ {} ]秒.", stopWatch.getTotalTimeSeconds());
} else {
stopWatch.stop();
log.info("定时任务执行完毕,但任务没有执行,因为当前函数不是公用函数,消耗时间[ {} ]秒.", stopWatch.getTotalTimeSeconds());
}
} catch (Exception e) {
log.error("[调用定时函数失败,运行异常]", e);
}
}
}
ok到这里就结束了
最后只需要写一个这样的业务类就可以调度了
package com.techhero.base.transdata.service;
import com.techhero.common.model.abs.QuartzControl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
@Slf4j
public class JobService {
public void exeIntervalTime(QuartzControl quartzControl) {
log.info("{},测试时间间隔任务.....",new Date().toLocaleString());
}
public void exeOnce(QuartzControl quartzControl) {
log.info("{},测试只执行一次任务.....",new Date().toLocaleString());
}
public void exeCron(QuartzControl quartzControl) {
log.info("{},测试只执行一次任务.....",new Date().toLocaleString());
}
}
最后在子系统配置文件中加入这个配置就行
task:
switch: true
最后数据库脚本
oracle版本
DELETE FROM QRTZ_FIRED_TRIGGERS;
DELETE FROM QRTZ_SIMPLE_TRIGGERS;
DELETE FROM QRTZ_SIMPROP_TRIGGERS;
DELETE FROM QRTZ_CRON_TRIGGERS;
DELETE FROM QRTZ_BLOB_TRIGGERS;
DELETE FROM QRTZ_TRIGGERS;
DELETE FROM QRTZ_JOB_DETAILS;
DELETE FROM QRTZ_CALENDARS;
DELETE FROM QRTZ_PAUSED_TRIGGER_GRPS;
DELETE FROM QRTZ_LOCKS;
DELETE FROM QRTZ_SCHEDULER_STATE;
DROP TABLE QRTZ_CALENDARS;
DROP TABLE QRTZ_FIRED_TRIGGERS;
DROP TABLE QRTZ_BLOB_TRIGGERS;
DROP TABLE QRTZ_CRON_TRIGGERS;
DROP TABLE QRTZ_SIMPLE_TRIGGERS;
DROP TABLE QRTZ_SIMPROP_TRIGGERS;
DROP TABLE QRTZ_TRIGGERS;
DROP TABLE QRTZ_JOB_DETAILS;
DROP TABLE QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE QRTZ_LOCKS;
DROP TABLE QRTZ_SCHEDULER_STATE;
CREATE TABLE QRTZ_JOB_DETAILS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
JOB_CLASS_NAME VARCHAR2(250) NOT NULL,
IS_DURABLE VARCHAR2(1) NOT NULL,
IS_NONCONCURRENT VARCHAR2(1) NOT NULL,
IS_UPDATE_DATA VARCHAR2(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_TRIGGERS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
JOB_NAME VARCHAR2(200) NOT NULL,
JOB_GROUP VARCHAR2(200) NOT NULL,
DESCRIPTION VARCHAR2(250) NULL,
NEXT_FIRE_TIME NUMBER(13) NULL,
PREV_FIRE_TIME NUMBER(13) NULL,
PRIORITY NUMBER(13) NULL,
TRIGGER_STATE VARCHAR2(16) NOT NULL,
TRIGGER_TYPE VARCHAR2(8) NOT NULL,
START_TIME NUMBER(13) NOT NULL,
END_TIME NUMBER(13) NULL,
CALENDAR_NAME VARCHAR2(200) NULL,
MISFIRE_INSTR NUMBER(2) NULL,
JOB_DATA BLOB NULL,
CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK 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 VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
REPEAT_COUNT NUMBER(7) NOT NULL,
REPEAT_INTERVAL NUMBER(12) NOT NULL,
TIMES_TRIGGERED NUMBER(10) NOT NULL,
CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CRON_TRIGGERS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CRON_EXPRESSION VARCHAR2(120) NOT NULL,
TIME_ZONE_ID VARCHAR2(80),
CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
STR_PROP_1 VARCHAR2(512) NULL,
STR_PROP_2 VARCHAR2(512) NULL,
STR_PROP_3 VARCHAR2(512) NULL,
INT_PROP_1 NUMBER(10) NULL,
INT_PROP_2 NUMBER(10) NULL,
LONG_PROP_1 NUMBER(13) NULL,
LONG_PROP_2 NUMBER(13) NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR2(1) NULL,
BOOL_PROP_2 VARCHAR2(1) NULL,
CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_BLOB_TRIGGERS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
BLOB_DATA BLOB NULL,
CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CALENDARS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
CALENDAR_NAME VARCHAR2(200) NOT NULL,
CALENDAR BLOB NOT NULL,
CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
ENTRY_ID VARCHAR2(95) NOT NULL,
TRIGGER_NAME VARCHAR2(200) NOT NULL,
TRIGGER_GROUP VARCHAR2(200) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
FIRED_TIME NUMBER(13) NOT NULL,
SCHED_TIME NUMBER(13) NOT NULL,
PRIORITY NUMBER(13) NOT NULL,
STATE VARCHAR2(16) NOT NULL,
JOB_NAME VARCHAR2(200) NULL,
JOB_GROUP VARCHAR2(200) NULL,
IS_NONCONCURRENT VARCHAR2(1) NULL,
REQUESTS_RECOVERY VARCHAR2(1) NULL,
CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE QRTZ_SCHEDULER_STATE
(
SCHED_NAME VARCHAR2(120) NOT NULL,
INSTANCE_NAME VARCHAR2(200) NOT NULL,
LAST_CHECKIN_TIME NUMBER(13) NOT NULL,
CHECKIN_INTERVAL NUMBER(13) NOT NULL,
CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE QRTZ_LOCKS
(
SCHED_NAME VARCHAR2(120) NOT NULL,
LOCK_NAME VARCHAR2(40) NOT NULL,
CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
MYSQL 版本
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(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) 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)
);
CREATE TABLE QRTZ_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) 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(200) 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(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(200) 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(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) 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(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) 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(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) 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(200) NULL,
JOB_GROUP VARCHAR(200) 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(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) 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(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);