文章参考1:https://blog.csdn.net/fyfguuug/article/details/79358159
文章参考2:https://blog.csdn.net/qq_41866572/article/details/80061853
文章参考3:https://blog.csdn.net/wanghaoalain/article/details/79288387
文章参考4:https://blog.csdn.net/chenyao1994/article/details/80482053
实现job的操作:https://blog.csdn.net/lfy609225258/article/details/96105538
感谢作者!
如果仅仅只是使用定时任务,可以使用spring的schedule实现,方便,代码量少.易于实现,但是,思考一个问题.
当使用分布式进行项目部署的时候,每一哥jar包中都包含一个定时任务,就会出现所有的服务器都在跑同一个定时,出现一个定时任务执行多次的情况,会出现很多问题.
最简单的解决方式,改项目,只留一个项目存在定时任务,其他都没有,但是,这样就会出现单点故障的问题.并不是最好的解决方式.
最好的方式是,使用quartz进行定时任务的调度.
1.我们可以实现多个定时任务进行调度。
2.可以实现与代码的解耦,通过配置文件的方式进行配置。
3.功能强大,可以通过cron表达式设置复杂的时间任务调度。
1.job:(被任务调度的接口),我们需要实现job,和继承TimerTask重写run方法一样,重写job中的excute方法,excute方法是任务调度的方法执行位置。
2.JobDetail:必须通过JobDetail来实现Job实例,(基于builder模式实现的)
3.trigger(包括:CronTrigger 和simpleTrigger):指定任务调度的频率时间。何时进行任务调度(基于builder模式实现的)触发器
4.scheduler:结合jobdetail 实例和trigger实例,进行调度的触发的调度器(基于factory模式)。
一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。离开了db将无法感知.
因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。Quartz 包括了所有被支持的数据库平台的 SQL 脚本。这是mysql的表.
注意:创建的表表名都是小写的,在代码中使用的是大写的表名;在liunx中的mysql数据库默认是大小写敏感的,因此使用liunx的数据库会出现找不到表的情况,酌情修改表或是改变数据库配置
Caused by: java.sql.SQLSyntaxErrorException: Table 'schedule_quartz.QRTZ_TRIGGERS' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.17.jar:8.0.17]
表中所有字段详解: https://blog.csdn.net/sqlgao22/article/details/100697214
所有资源地址: https://download.csdn.net/download/sqlgao22/11705738
/*
Navicat MySQL Data Transfer
Source Server : 192.168.163.128_3306
Source Server Version : 50540
Source Host : 192.168.163.128:3306
Source Database : primer
Target Server Type : MYSQL
Target Server Version : 50540
File Encoding : 65001
Date: 2018-08-29 22:56:23
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for qrtz_blob_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_blob_triggers`;
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,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_calendars
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_calendars`;
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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_cron_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_cron_triggers`;
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(120) NOT NULL,
`TIME_ZONE_ID` varchar(80) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_fired_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_fired_triggers`;
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` int(11) NOT NULL,
`STATE` varchar(16) NOT NULL,
`JOB_NAME` varchar(200) DEFAULT NULL,
`JOB_GROUP` varchar(200) DEFAULT NULL,
`IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
`REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_job_details
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_job_details`;
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) DEFAULT 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,
PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_locks
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_locks`;
CREATE TABLE `qrtz_locks` (
`SCHED_NAME` varchar(120) NOT NULL,
`LOCK_NAME` varchar(40) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_paused_trigger_grps
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
CREATE TABLE `qrtz_paused_trigger_grps` (
`SCHED_NAME` varchar(120) NOT NULL,
`TRIGGER_GROUP` varchar(200) NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_scheduler_state
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_scheduler_state`;
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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_simple_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simple_triggers`;
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`),
CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_simprop_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
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) DEFAULT NULL,
`STR_PROP_2` varchar(512) DEFAULT NULL,
`STR_PROP_3` varchar(512) DEFAULT NULL,
`INT_PROP_1` int(11) DEFAULT NULL,
`INT_PROP_2` int(11) DEFAULT NULL,
`LONG_PROP_1` bigint(20) DEFAULT NULL,
`LONG_PROP_2` bigint(20) DEFAULT NULL,
`DEC_PROP_1` decimal(13,4) DEFAULT NULL,
`DEC_PROP_2` decimal(13,4) DEFAULT NULL,
`BOOL_PROP_1` varchar(1) DEFAULT NULL,
`BOOL_PROP_2` varchar(1) DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for qrtz_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_triggers`;
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) DEFAULT NULL,
`NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
`PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
`PRIORITY` int(11) DEFAULT NULL,
`TRIGGER_STATE` varchar(16) NOT NULL,
`TRIGGER_TYPE` varchar(8) NOT NULL,
`START_TIME` bigint(13) NOT NULL,
`END_TIME` bigint(13) DEFAULT NULL,
`CALENDAR_NAME` varchar(200) DEFAULT NULL,
`MISFIRE_INSTR` smallint(2) DEFAULT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
org.springframework
spring-context-support
org.quartz-scheduler
quartz
2.3.0
com.alibaba
druid
1.1.12
这里要注意,使用分布式集群跑定时,需要使用到db持久化,所以需要所有的节点共享一个数据源.
关键配置都有注释.
#============================================================================
# Configure JobStore
# Using Spring datasource in SchedulerConfig.java
# Spring uses LocalDataSourceJobStore extension of JobStoreCMT
#============================================================================
org.quartz.jobStore.useProperties=false
#表名的前缀
org.quartz.jobStore.tablePrefix = QRTZ_
#isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中
org.quartz.jobStore.isClustered = true
#clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒),默认值是 15000
org.quartz.jobStore.clusterCheckinInterval = 3000
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.txIsolationLevelReadCommitted = true
#class属性为 JobStoreTX,将任务持久化到数据中。quartz依赖于数据库查询任务状态
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#============================================================================
# Configure Main Scheduler Properties
# Needed to manage cluster instances
#============================================================================
#instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。
org.quartz.scheduler.instanceName = ClusterQuartz
#instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID
org.quartz.scheduler.instanceId= AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
#============================================================================
# Configure ThreadPool
# Can also be configured in spring configuration
# 此处使用的java的线程池
#============================================================================
#org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#org.quartz.threadPool.threadCount = 5
#org.quartz.threadPool.threadPriority = 5
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
几乎每行代码都有详细的注释.这边就不详细写了.请看代码.
package com.jd.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.jd.task.SimpleJob;
import com.jd.task.SimpleJobTwo;
import org.quartz.Scheduler;
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.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.Executor;
@Configuration
public class TaskConfig {
//配置数据源
//这里可以不使用@Bean交给spring管理,否则可能出现默认数据源的问题.
//@Bean
public DataSource druidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/schedule?serverTimezone=GMT%2B8");
dataSource.setUsername("root");
dataSource.setPassword("112233");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
return dataSource;
}
//配置quartz配置文件
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
// 在quartz.properties中的属性被读取并注入后再初始化对象
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
//配置定时任务1
@Bean
public JobDetailFactoryBean job1() {
JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
//配置任务的具体实现
jobDetail.setJobClass(SimpleJob.class);
//是否持久化
jobDetail.setDurability(true);
//出现异常是否重新执行
jobDetail.setRequestsRecovery(true);
//配置定时任务信息
jobDetail.setName("job1111------");
jobDetail.setGroup("quartzTest--------");
jobDetail.setDescription("这是job1111");
return jobDetail;
}
//配置定时任务2
@Bean
public JobDetailFactoryBean job2() {
JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
jobDetail.setJobClass(SimpleJobTwo.class);
jobDetail.setDurability(true);
jobDetail.setRequestsRecovery(true);
jobDetail.setName("job22222------");
jobDetail.setGroup("quartzTest--------");
jobDetail.setDescription("这是job2222");
return jobDetail;
}
//配置任务定时规则1
@Bean
public CronTriggerFactoryBean trigger1() {
CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean();
//定时规则的分组
cronTrigger.setGroup("TriggerTest11111");
cronTrigger.setName("trigger1");
//配置执行的任务jobdetail
cronTrigger.setJobDetail(job1().getObject());
//配置执行规则 每5秒执行一次
cronTrigger.setCronExpression("0/5 * * * * ?");
return cronTrigger;
}
//配置任务定时规则2
@Bean
public CronTriggerFactoryBean trigger2() {
CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean();
cronTrigger.setGroup("TriggerTest2222");
cronTrigger.setName("trigger2");
cronTrigger.setJobDetail(job2().getObject());
cronTrigger.setCronExpression("0/8 * * * * ?");
return cronTrigger;
}
//配置任务调度工厂,用来生成任务调度器,这是quartz的核心
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//开启更新job
factory.setOverwriteExistingJobs(true);
//如果不配置就会使用quartz.properties中的instanceName
//factory.setSchedulerName("Cluster_Scheduler");
//配置数据源,这是quartz使用的表的数据库存放位置
factory.setDataSource(druidDataSource());
//设置实例在spring容器中的key
factory.setApplicationContextSchedulerContextKey("applicationContext");
//配置线程池
factory.setTaskExecutor(schedulerThreadPool());
//配置配置文件
factory.setQuartzProperties(quartzProperties());
//配置任务执行规则,参数是一个可变数组
factory.setTriggers(trigger1().getObject(),trigger2().getObject());
return factory;
}
//开启当前的任务调度器
@Bean
public Scheduler scheduler() throws Exception {
Scheduler scheduler = schedulerFactoryBean().getScheduler();
TriggerKey triggerKey1 = TriggerKey.triggerKey("trigger1", "TriggerTest11111");
/*========如果有必要可以配置删除任务,开始====================*/
//停止触发器
scheduler.pauseTrigger(triggerKey1);
//移除触发器
scheduler.unscheduleJob(triggerKey1);
JobKey jobKey1 = JobKey.jobKey("job1111------", "quartzTest--------");
//删除任务
boolean b = scheduler.deleteJob(jobKey1);
System.out.println(b);
/*=========结束====================*/
scheduler.start();
return scheduler;
}
//线程池配置
@Bean
public Executor schedulerThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(50);
return executor;
}
}
定时任务需要实现job接口,但是quartz已经有了一个简单的抽象实现,简化了代码量.只需要直接继承即可.
这里贴一下源代码,一开始看资料有实现job接口的,有继承QuartzJobBean 的,没看太懂,后来看源码才知道了.
public abstract class QuartzJobBean implements Job
写定时任务:
@Component
public class SimpleJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("=========SimpleJob中的executeInternal方法执行了===="+new Date());
}
}
@Component
public class SimpleJobTwo extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("-----------------SimpleJobTwo的任务执行了------"+new Date());
}
}
将项目打成jar包,运行.
将原项目改端口,重新运行.
当只有一个项目的时候,两个会在同一个上执行,如上图.
当两个启动时:
会进行分开进行:
解决了单点故障,也能执行定时.
java.lang.NullPointerException: null
at com.jd.jrdp.agile.bi.service.task2.CheckExportOverDueSchedulerJob.checkExportData(CheckExportOverDueSchedulerJob.java:38) ~[classes!/:na]
at com.jd.jrdp.agile.bi.service.task2.CheckExportOverDueSchedulerJob.executeInternal(CheckExportOverDueSchedulerJob.java:56) ~[classes!/:na]
Quartz初始化是自己的JobContext,不同于Spring的ApplicationContext,所以无法直接注入,导致使用时产生空指针异常!
版本也有关系:
spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。至于原因,则是spring对于quartz的支持实现org.springframework.scheduling.quartz.CronTriggerBean继承了org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是个类,而在quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器(trigger)。
自定义一个类.继承JobFactory.重写createInstance方法,
@Component
public class MyJobFactory extends SpringBeanJobFactory {
@Autowired
//注入autowire的对象工厂
private AutowireCapableBeanFactory beanFactory;
//重写Job工厂的createJobInstance方法
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object object = super.createJobInstance(bundle);
//在autowired中手动加入创建出来的对象
beanFactory.autowireBean(object);
return object;
}
}
注意配置类中的变化:
需要在调度中心SchedulerFactoryBean中额外配置使用自己的JobFactory,以及配置延迟加载.
//将自定义的MyJobFactory注入配置类,并添加如下配置,
//配置使用spring的autowired的对象,在job中进行对象的注入
factory.setJobFactory(jobFactory);
//设置延时启动,保证job中的属性的注入
factory.setStartupDelay(5);
到此为止,问题就解决了.