Spring整合quartz2.2.3总结,quartz动态定时任务,Quartz定时任务集群配置
Spring整合quartz2.2.3总结,quartz动态定时任务,Quartz定时任务集群配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
©Copyright 蕃薯耀 2017年9月6日
http://www.cnblogs.com/fanshuyao/
一、Spring整合Quartz
使用的是spring4:4.3.9.RELEASE,Quartz2:2.2.3
二、引用Quartz 的Jar包
maven方式:(Spring不说了)
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- <version>${quartz.version}</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz-jobs</artifactId>
- <version>${quartz.version}</version>
- </dependency>
三、在数据库创建Quartz 相关的表(下面的数据库为:tables_mysql_innodb.sql),先创建表,然后再执下面的索引,避免警告。(更多表见http://fanshuyao.iteye.com/blog/2392350)
- #
- # In your Quartz properties file, you'll need to set
- # org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
- #
- #
- # By: Ron Cordell - roncordell
- # I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
- 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))
- ENGINE=InnoDB;
- 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))
- ENGINE=InnoDB;
- 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))
- ENGINE=InnoDB;
- 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),
- 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))
- ENGINE=InnoDB;
- 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))
- ENGINE=InnoDB;
- 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),
- INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
- FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
- REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
- ENGINE=InnoDB;
- 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;
- 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;
- 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))
- ENGINE=InnoDB;
- 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;
- CREATE TABLE QRTZ_LOCKS (
- SCHED_NAME VARCHAR(120) NOT NULL,
- LOCK_NAME VARCHAR(40) NOT NULL,
- PRIMARY KEY (SCHED_NAME,LOCK_NAME))
- ENGINE=InnoDB;
- -- 这是是索引了--------------------------------------------
- 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);
- commit;
四、新建一个Quartz相关的Properties文件:spring-quartz.properties,此配置为官网例子的配置
- #配置见:http://www.quartz-scheduler.org/documentation/quartz-2.2.x/configuration/ConfigJDBCJobStoreClustering.html
- #============================================================================
- # Configure Main Scheduler Properties
- #============================================================================
- org.quartz.scheduler.instanceName = MyClusteredScheduler
- org.quartz.scheduler.instanceId = AUTO
- #============================================================================
- # Configure ThreadPool
- #============================================================================
- org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
- org.quartz.threadPool.threadCount = 25
- org.quartz.threadPool.threadPriority = 5
- #============================================================================
- # Configure JobStore
- #============================================================================
- org.quartz.jobStore.misfireThreshold = 60000
- org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
- org.quartz.jobStore.useProperties = false
- org.quartz.jobStore.dataSource = myDS
- org.quartz.jobStore.tablePrefix = QRTZ_
- org.quartz.jobStore.isClustered = true
- org.quartz.jobStore.clusterCheckinInterval = 20000
五、整合Spring和Quartz,在Spring.xml配置
- <bean id="customJobFactory" class="cn.imovie.manage.task.job.CustomJobFactory"></bean>
- <!-- 定时任务配置 start -->
- <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="dataSource" ref="dataSource"></property>
- <!-- 可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->
- <property name="overwriteExistingJobs" value="true" />
- <!-- 必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->
- <property name="startupDelay" value="2" />
- <!-- 设置自动启动 -->
- <property name="autoStartup" value="true" />
- <property name="jobFactory" ref="customJobFactory"></property>
- <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
- <property name="configLocation" value="classpath:spring-quartz.properties" />
- </bean>
- <!-- 定时任务配置 end -->
其中customJobFactory 是为了解决Spring quartz Job不能依赖注入。
代码如下:
- import org.quartz.spi.TriggerFiredBundle;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
- import org.springframework.scheduling.quartz.SpringBeanJobFactory;
- public class CustomJobFactory extends SpringBeanJobFactory{
- @Autowired
- private AutowireCapableBeanFactory capableBeanFactory;
- @Override
- protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
- //调用父类的方法
- Object jobInstance = super.createJobInstance(bundle);
- //进行注入
- capableBeanFactory.autowireBean(jobInstance);
- return jobInstance;
- }
- }
六、Quartz定时任务主代码:
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import java.util.Set;
- import org.quartz.CronScheduleBuilder;
- import org.quartz.CronTrigger;
- import org.quartz.Job;
- import org.quartz.JobBuilder;
- import org.quartz.JobDetail;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobKey;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.quartz.SimpleScheduleBuilder;
- import org.quartz.SimpleTrigger;
- import org.quartz.Trigger;
- import org.quartz.TriggerBuilder;
- import org.quartz.TriggerKey;
- import org.quartz.impl.matchers.GroupMatcher;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Repository;
- import cn.imovie.common.utils.CC;
- import cn.imovie.common.utils.DateUtils;
- import cn.imovie.common.utils.JasonUtils;
- import cn.imovie.common.utils.StrUtils;
- import cn.imovie.dao.SchedulerManageDao;
- import cn.imovie.entity.task.ScheduleJob;
- @Repository
- public class SchedulerManageDaoImpl implements SchedulerManageDao{
- private Logger log = LoggerFactory.getLogger(SchedulerManageDaoImpl.class);
- @Autowired
- private Scheduler scheduler;
- /**
- * 新增任务
- * @param scheduleJob
- */
- @Override
- public void add(ScheduleJob scheduleJob) throws Exception{
- if(!StrUtils.isBlank(scheduleJob.getCronExpression())){
- this.addJobCron(scheduleJob);
- }else{
- this.addJobSimple(scheduleJob);
- }
- }
- /**
- * 更新任务
- * @param scheduleJob
- */
- @Override
- public void update(ScheduleJob scheduleJob) throws Exception{
- if(!StrUtils.isBlank(scheduleJob.getCronExpression())){
- this.updateJobCron(scheduleJob);
- }else{
- this.updateJobSimple(scheduleJob);
- }
- }
- /**
- * 新增任务
- * @param scheduleJob
- * @throws Exception
- */
- @SuppressWarnings("unchecked")
- @Override
- public void addJobCron(ScheduleJob scheduleJob) throws Exception{
- TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- //任务触发
- Trigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
- if (null == trigger) {
- JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(scheduleJob.getClazz()))
- .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build();
- jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
- CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
- /*withMisfireHandlingInstructionDoNothing
- ——不触发立即执行
- ——等待下次Cron触发频率到达时刻开始按照Cron频率依次执行
- withMisfireHandlingInstructionIgnoreMisfires
- ——以错过的第一个频率时间立刻开始执行
- ——重做错过的所有频率周期后
- ——当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行
- withMisfireHandlingInstructionFireAndProceed
- ——以当前时间为触发频率立刻触发一次执行
- ——然后按照Cron频率依次执行*/
- trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).withSchedule(cronScheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
- scheduler.scheduleJob(jobDetail, trigger);
- log.info(CC.LOG_PREFIX + "新增Cron任务:"+JasonUtils.Object2String(scheduleJob));
- }else {
- // Trigger已存在,那么更新相应的定时设置
- //表达式调度构建器
- /*CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
- //按新的cronExpression表达式重新构建trigger
- trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- JobDetail jobDetail = scheduler.getJobDetail(jobKey);
- jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
- //按新的trigger重新设置job执行
- scheduler.rescheduleJob(triggerKey, trigger);
- log.info(CC.LOG_PREFIX + "任务"+JasonUtils.Object2String(scheduleJob)+"已经存在,更新trigger");*/
- this.updateJobCron(scheduleJob);
- }
- }
- /**
- * 更新任务的时间表达式
- * @param scheduleJob
- */
- @Override
- public void updateJobCron(ScheduleJob scheduleJob) throws Exception{
- /*TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- //获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
- CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
- //表达式调度构建器
- CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
- //按新的cronExpression表达式重新构建trigger
- trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder.withMisfireHandlingInstructionDoNothing()).build();
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- JobDetail jobDetail = scheduler.getJobDetail(jobKey);
- jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
- //按新的trigger重新设置job执行
- scheduler.rescheduleJob(triggerKey, trigger);*/
- //为什么要删除再新增呢?因为不这样,JobDetail的JobDataMap不更新。注解什么都试过了,没起作用。
- this.deleteJob(scheduleJob);
- this.addJobCron(scheduleJob);
- log.info(CC.LOG_PREFIX + "更新Cron任务(先删除再更新):"+JasonUtils.Object2String(scheduleJob));
- }
- /**
- * 新增任务
- * @param scheduleJob
- * @throws Exception
- */
- @Override
- @SuppressWarnings("unchecked")
- public void addJobSimple(ScheduleJob scheduleJob) throws Exception{
- TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- //任务触发
- SimpleTrigger trigger = (SimpleTrigger) scheduler.getTrigger(triggerKey);
- if (null == trigger) {
- JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(scheduleJob.getClazz()))
- .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build();
- jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
- SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
- Date triggerStartTime = new Date();
- if("秒".equals(scheduleJob.getTimeType()) ||
- "second".equalsIgnoreCase(scheduleJob.getTimeType())){
- simpleScheduleBuilder.withIntervalInSeconds(scheduleJob.getTimeValue());
- triggerStartTime = DateUtils.dateAddSeconds(triggerStartTime, scheduleJob.getTimeValue());
- }else if("分".equals(scheduleJob.getTimeType()) || "分钟".equals(scheduleJob.getTimeType()) ||
- "minute".equalsIgnoreCase(scheduleJob.getTimeType())){
- simpleScheduleBuilder.withIntervalInMinutes(scheduleJob.getTimeValue());
- triggerStartTime = DateUtils.dateAddMinutes(triggerStartTime, scheduleJob.getTimeValue());
- }else if("时".equals(scheduleJob.getTimeType()) || "小时".equals(scheduleJob.getTimeType()) ||
- "hour".equalsIgnoreCase(scheduleJob.getTimeType())){
- simpleScheduleBuilder.withIntervalInHours(scheduleJob.getTimeValue());
- triggerStartTime = DateUtils.dateAddHours(triggerStartTime, scheduleJob.getTimeValue());
- }else if("天".equals(scheduleJob.getTimeType()) ||
- "date".equalsIgnoreCase(scheduleJob.getTimeType())){
- simpleScheduleBuilder.withIntervalInHours(scheduleJob.getTimeValue()*24);//2017-09-15修正问题,少了24
- triggerStartTime = DateUtils.dateAddDays(triggerStartTime, scheduleJob.getTimeValue());
- }
- trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup())
- .startAt(triggerStartTime).withSchedule(simpleScheduleBuilder.repeatForever().withMisfireHandlingInstructionNextWithRemainingCount()).build();
- scheduler.scheduleJob(jobDetail, trigger);
- log.info(CC.LOG_PREFIX + "新增简单任务:"+JasonUtils.Object2String(scheduleJob));
- }else {
- this.updateJobCron(scheduleJob);
- }
- }
- /**
- * 更新任务的时间表达式
- * @param scheduleJob
- * @throws Exception
- */
- @Override
- public void updateJobSimple(ScheduleJob scheduleJob) throws Exception{
- //为什么要删除再新增呢?因为不这样,JobDetail的JobDataMap不更新。注解什么都试过了,没起作用。
- this.deleteJob(scheduleJob);
- this.addJobSimple(scheduleJob);
- log.info(CC.LOG_PREFIX + "更新简单任务(先删除再更新):"+JasonUtils.Object2String(scheduleJob));
- }
- /**
- * 暂停任务
- * @param scheduleJob
- * @throws Exception
- */
- @Override
- public void pauseJob(ScheduleJob scheduleJob) throws Exception{
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.pauseJob(jobKey);
- log.info(CC.LOG_PREFIX + "暂停任务:"+JasonUtils.Object2String(scheduleJob));
- }
- /**
- * 暂停全部任务
- * @throws SchedulerException
- */
- @Override
- public void pauseAll() throws Exception{
- scheduler.pauseAll();
- log.info(CC.LOG_PREFIX + "暂停所有任务");
- }
- /**
- * 恢复任务
- * @param scheduleJob
- * @throws Exception
- */
- @Override
- public void resumeJob(ScheduleJob scheduleJob) throws Exception{
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.resumeJob(jobKey);
- log.info(CC.LOG_PREFIX + "恢复任务:"+JasonUtils.Object2String(scheduleJob));
- }
- /**
- * 恢复所有任务
- * @throws Exception
- */
- @Override
- public void resumeAll() throws Exception{
- scheduler.resumeAll();
- log.info(CC.LOG_PREFIX + "恢复所有任务");
- }
- /**
- * 删除任务后,所对应的trigger也将被删除
- * @param scheduleJob
- * @throws Exception
- */
- @Override
- public void deleteJob(ScheduleJob scheduleJob) throws Exception{
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.pauseJob(jobKey);//先暂停任务
- scheduler.deleteJob(jobKey);//再删除任务
- log.info(CC.LOG_PREFIX + "删除任务:"+JasonUtils.Object2String(scheduleJob));
- }
- /**
- * 立即运行任务
- * @param scheduleJob
- * @throws Exception
- */
- @Override
- public void triggerJob(ScheduleJob scheduleJob) throws Exception{
- JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
- scheduler.triggerJob(jobKey);
- log.info(CC.LOG_PREFIX + "运行任务:"+JasonUtils.Object2String(scheduleJob));
- }
- /**
- * 获取quartz调度器的计划任务
- * @return
- */
- @Override
- public List<ScheduleJob> getScheduleJobList(){
- List<ScheduleJob> jobList = null;
- try {
- GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
- Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
- jobList = new ArrayList<ScheduleJob>();
- for (JobKey jobKey : jobKeys) {
- List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
- for (Trigger trigger : triggers) {
- ScheduleJob job = new ScheduleJob();
- job.setJobName(jobKey.getName());
- job.setJobGroup(jobKey.getGroup());
- job.setClazz(jobKey.getClass().toString());
- job.setJobDesc("触发器:" + trigger.getKey());
- Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
- job.setJobStatus(triggerState.name());
- if (trigger instanceof CronTrigger) {
- CronTrigger cronTrigger = (CronTrigger) trigger;
- String cronExpression = cronTrigger.getCronExpression();
- job.setCronExpression(cronExpression);
- }else if(trigger instanceof SimpleTrigger){
- SimpleTrigger simpleTrigger = (SimpleTrigger) trigger;
- long milliseconds = simpleTrigger.getRepeatInterval();
- job.setTimeValue((int) (milliseconds/1000));
- }
- jobList.add(job);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return jobList;
- }
- /**
- * 获取quartz调度器的运行任务
- * @return
- */
- @Override
- public List<ScheduleJob> getScheduleJobRunningList(){
- List<ScheduleJob> jobList = null;
- try {
- List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
- jobList = new ArrayList<ScheduleJob>(executingJobs.size());
- for (JobExecutionContext executingJob : executingJobs) {
- ScheduleJob job = new ScheduleJob();
- JobDetail jobDetail = executingJob.getJobDetail();
- JobKey jobKey = jobDetail.getKey();
- Trigger trigger = executingJob.getTrigger();
- job.setJobName(jobKey.getName());
- job.setJobGroup(jobKey.getGroup());
- job.setClazz(jobKey.getClass().toString());
- job.setJobDesc("触发器:" + trigger.getKey());
- Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
- job.setJobStatus(triggerState.name());
- if (trigger instanceof CronTrigger) {
- CronTrigger cronTrigger = (CronTrigger) trigger;
- String cronExpression = cronTrigger.getCronExpression();
- job.setCronExpression(cronExpression);
- }else if(trigger instanceof SimpleTrigger){
- SimpleTrigger simpleTrigger = (SimpleTrigger) trigger;
- long milliseconds = simpleTrigger.getRepeatInterval();
- job.setTimeValue((int) (milliseconds/1000));
- }
- jobList.add(job);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return jobList;
- }
- }
SchedulerManageDao接口:
- import java.util.List;
- import cn.imovie.entity.task.ScheduleJob;
- public interface SchedulerManageDao {
- /**
- * 新增任务
- * @param scheduleJob
- * @throws Exception
- */
- public void addJobCron(ScheduleJob scheduleJob) throws Exception;
- /**
- * 暂停任务
- * @param scheduleJob
- */
- public void pauseJob(ScheduleJob scheduleJob) throws Exception;
- /**
- * 暂停全部任务
- */
- public void pauseAll() throws Exception;
- /**
- * 恢复任务
- * @param scheduleJob
- */
- public void resumeJob(ScheduleJob scheduleJob) throws Exception;
- /**
- * 恢复所有任务
- */
- public void resumeAll() throws Exception;
- /**
- * 删除任务后,所对应的trigger也将被删除
- * @param scheduleJob
- */
- public void deleteJob(ScheduleJob scheduleJob) throws Exception;
- /**
- * 立即运行任务
- * @param scheduleJob
- */
- public void triggerJob(ScheduleJob scheduleJob) throws Exception;
- /**
- * 更新任务的时间表达式
- * @param scheduleJob
- */
- public void updateJobCron(ScheduleJob scheduleJob) throws Exception;
- /**
- * 获取quartz调度器的计划任务
- * @return
- */
- public List<ScheduleJob> getScheduleJobList();
- /**
- * 获取quartz调度器的运行任务
- * @return
- */
- public List<ScheduleJob> getScheduleJobRunningList();
- public void addJobSimple(ScheduleJob scheduleJob) throws Exception;
- public void updateJobSimple(ScheduleJob scheduleJob) throws Exception;
- /**
- * 如果scheduleJob.getCronExpression()表达式不为空,使用表达式方式,如果为空,则使用简单方式
- * @param scheduleJob
- */
- public void add(ScheduleJob scheduleJob) throws Exception;
- /**
- * 如果scheduleJob.getCronExpression()表达式不为空,使用表达式方式,如果为空,则使用简单方式
- * @param scheduleJob
- */
- public void update(ScheduleJob scheduleJob) throws Exception;
- }
七、自定义一张表,用来保存设置定时任务的时间等信息,方便取出来显示
因为Quartz定时任务设置的时间都是转为毫秒后保存的,所以当你需要将设置当时的具体时间取出来显示是还原不了的,所以创建一张自定义表保存定时任务的信息。
表主要是分为表达式和简单的时间配置2种,定时任务优化判断cron_expression是否为空,如果不为空,优先使用表达式来生成动态定时任务,如果为空,则通过获取time_value、time_type来设置定时任务。
表结构(Mysql)如下:
- CREATE TABLE schedule_job(
- schedule_job_id BIGINT PRIMARY KEY COMMENT 'ID主键' ,
- job_name VARCHAR(200) NOT NULL COMMENT '任务名称',
- job_group VARCHAR(200) NOT NULL COMMENT '任务分组',
- clazz VARCHAR(500) NOT NULL COMMENT '定时任务对应的类(包括包路径)',
- job_status VARCHAR(2) NOT NULL COMMENT '任务状态 1禁用 2启用',
- cron_expression VARCHAR(200) COMMENT '任务运行时间表达式',
- time_value INT COMMENT '简单时间格式的值',
- time_type VARCHAR(50) COMMENT '简单时间格式的类型:天、时、分、秒',
- job_desc VARCHAR(500) COMMENT '任务描述',
- create_man BIGINT NOT NULL,
- create_time DATETIME NOT NULL,
- update_man BIGINT,
- update_time DATETIME
- );
对应的类(ScheduleJob)如下:
- import java.io.Serializable;
- import java.util.Date;
- import com.dexcoder.dal.annotation.Table;
- import com.dexcoder.dal.annotation.Transient;
- @SuppressWarnings("serial")
- @Table(name = "schedule_job", pkField = "scheduleJobId", pkColumn = "schedule_job_id")
- public class ScheduleJob implements Serializable{
- private Long scheduleJobId;
- /** 任务名称 */
- private String jobName;
- /** 任务分组 */
- private String jobGroup;
- /** 定时任务对应的类(包括包路径),如:cn.imovie.manage.task.job.TicketMoneyLessThanNormalWarn */
- private String clazz;
- /** 任务状态:1禁用 2启用*/
- private String jobStatus;
- /** 任务运行时间表达式 */
- private String cronExpression;
- /** 简单的时间值 */
- private Integer timeValue;
- /** 时间类型:秒、分、小时、天 */
- private String timeType;
- /** 任务描述 */
- private String jobDesc;
- private Long createMan;
- private Date createTime;
- private Long updateMan;
- private Date updateTime;
- // 非持久化属性
- private String createManText;
- private String updateManText;
- public Long getScheduleJobId() {
- return scheduleJobId;
- }
- public void setScheduleJobId(Long scheduleJobId) {
- this.scheduleJobId = scheduleJobId;
- }
- public String getJobName() {
- return jobName;
- }
- public void setJobName(String jobName) {
- this.jobName = jobName;
- }
- public String getJobGroup() {
- return jobGroup;
- }
- public void setJobGroup(String jobGroup) {
- this.jobGroup = jobGroup;
- }
- public String getClazz() {
- return clazz;
- }
- public void setClazz(String clazz) {
- this.clazz = clazz;
- }
- public String getJobStatus() {
- return jobStatus;
- }
- public void setJobStatus(String jobStatus) {
- this.jobStatus = jobStatus;
- }
- public String getCronExpression() {
- return cronExpression;
- }
- public void setCronExpression(String cronExpression) {
- this.cronExpression = cronExpression;
- }
- public Integer getTimeValue() {
- return timeValue;
- }
- public void setTimeValue(Integer timeValue) {
- this.timeValue = timeValue;
- }
- public String getTimeType() {
- return timeType;
- }
- public void setTimeType(String timeType) {
- this.timeType = timeType;
- }
- public String getJobDesc() {
- return jobDesc;
- }
- public void setJobDesc(String jobDesc) {
- this.jobDesc = jobDesc;
- }
- public Long getCreateMan() {
- return createMan;
- }
- public void setCreateMan(Long createMan) {
- this.createMan = createMan;
- }
- public Date getCreateTime() {
- return createTime;
- }
- public void setCreateTime(Date createTime) {
- this.createTime = createTime;
- }
- public Long getUpdateMan() {
- return updateMan;
- }
- public void setUpdateMan(Long updateMan) {
- this.updateMan = updateMan;
- }
- public Date getUpdateTime() {
- return updateTime;
- }
- public void setUpdateTime(Date updateTime) {
- this.updateTime = updateTime;
- }
- @Transient
- public String getCreateManText() {
- return createManText;
- }
- public void setCreateManText(String createManText) {
- this.createManText = createManText;
- }
- @Transient
- public String getUpdateManText() {
- return updateManText;
- }
- public void setUpdateManText(String updateManText) {
- this.updateManText = updateManText;
- }
- }
八、一个定时任务Job的例子(仅供参考):这里直接使用了service的注入,默认是不可以的,需要配置customJobFactory ,上面已经有说明。
- import java.util.Date;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.quartz.DisallowConcurrentExecution;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.quartz.PersistJobDataAfterExecution;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import cn.imovie.common.utils.CC;
- import cn.imovie.common.utils.StrUtils;
- import cn.imovie.entity.TsCinemaBasePriceLimit;
- import cn.imovie.entity.warn.Warning;
- import cn.imovie.manage.enums.WarnType;
- import cn.imovie.service.TsCinemaBasePriceLimitService;
- import cn.imovie.service.WarningService;
- @Component
- @PersistJobDataAfterExecution
- @DisallowConcurrentExecution
- public class CinemaSalePriceGreaterThanOtherPlatformJob implements Job{
- private Logger log = LoggerFactory.getLogger(CinemaSalePriceGreaterThanOtherPlatformJob.class);
- @Autowired
- private TsCinemaBasePriceLimitService tsCinemaBasePriceLimitService;
- @Autowired
- private WarningService warningService;
- @Override
- public void execute(JobExecutionContext context)
- throws JobExecutionException {
- Date currentTime = new Date();
- Map<String, List<TsCinemaBasePriceLimit>> map = new HashMap<String, List<TsCinemaBasePriceLimit>>();
- try {
- map = tsCinemaBasePriceLimitService.listCinemaSalePriceGreaterThanOtherPlatform("1,3", currentTime);
- } catch (Exception e) {
- e.printStackTrace();
- }
- if(!StrUtils.isEmptyMap(map)){
- List<TsCinemaBasePriceLimit> list_2d = map.get("2d");
- String reason = "2D或3D销售价格高于其它平台的价格设置";
- for (TsCinemaBasePriceLimit tsCinemaBasePriceLimit : list_2d) {
- Warning warning = new Warning();
- warning.setWarnType(WarnType.CINEMA_SALE_PRICE_GREATER_THAN_OTHER_PLATFORM.getValue());
- warning.setAssociatedTable("ts_cinema_base_price_limit");
- warning.setAssociatedTableId(tsCinemaBasePriceLimit.getPriceLimitId());
- warning.setReason(reason);
- warning.setCreateTime(currentTime);
- warning.setCreateMan(-999L);
- warningService.save(warning);
- }
- List<TsCinemaBasePriceLimit> list_3d = map.get("3d");
- for (TsCinemaBasePriceLimit tsCinemaBasePriceLimit_3d : list_3d) {
- Warning warning = new Warning();
- warning.setWarnType(WarnType.CINEMA_SALE_PRICE_GREATER_THAN_OTHER_PLATFORM.getValue());
- warning.setAssociatedTable("ts_cinema_base_price_limit");
- warning.setAssociatedTableId(tsCinemaBasePriceLimit_3d.getPriceLimitId());
- warning.setReason(reason);
- warning.setCreateTime(currentTime);
- warning.setCreateMan(-999L);
- warningService.save(warning);
- }
- }
- log.info(CC.LOG_PREFIX + "[CinemaSalePriceGreaterThanOtherPlatformJob]定时任务执行完毕。");
- }
- }
(如果你觉得文章对你有帮助,欢迎捐赠,^_^,谢谢!)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
©Copyright 蕃薯耀 2017年9月6日
http://www.cnblogs.com/fanshuyao/