Spring整合quartz2.2.3总结,quartz动态定时任务,Quartz定时任务集群配置
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
©Copyright 蕃薯耀 2017年9月6日
http://fanshuyao.iteye.com/
一、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),先创建表,然后再执下面的索引,避免警告。(更多表见附件: dbTables.zip)
# # 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://fanshuyao.iteye.com/
相关推荐
总之,结合Spring 4.0.6和Quartz 2.2.3构建集群示例,能够帮助你在大型分布式系统中实现灵活、可靠的定时任务调度。通过熟练掌握这一技术,你可以为企业的后台服务提供强大而稳定的定时任务处理能力。
spring boot+vue+quartz2.2.3整合定时调度系统持久化道mysql,sql脚本在项目里面。sql文件spring boot+vue+quartz2.2.3整合定时调度系统持久化道mysql
在 "Quartz2.2.3+Spring4.3.14整合demo" 项目中,我们看到的是一个示例,展示了如何在 Eclipse 开发环境中将这两个库结合使用。Eclipse 是一个流行的 Java IDE,它提供了丰富的功能来支持开发过程。 首先,`....
总之,Quartz 2.2.3的初始化SQL语句是搭建Quartz任务调度系统的重要环节,它们构建了存储任务调度数据的基础架构,使得Quartz能有效地管理、执行和监控定时任务。正确理解和使用这些SQL语句,有助于确保Quartz在各种...
总结来说,Quartz 2.2.3 是一个强大且灵活的定时任务框架,适用于各种 Java 应用场景,如批处理、后台服务、定时数据同步等。通过提供的 jar 包和 javadoc,开发者可以轻松集成并定制自己的任务调度系统。
综上所述,SpringBoot整合quartz 2.2.3和WebSocket通信是一项综合性的任务,涉及到数据库管理、定时任务调度和实时通信等多个领域。通过恰当的配置和编程,我们可以构建出高效、可扩展的微服务系统,满足复杂的企业...
总结来说,"quartz-2.2.3.zip"提供的资源可以帮助我们设置和运行Quartz作业调度系统,通过"quartz-2.2.3-sql"的SQL脚本创建必要的数据库表,而"quartz-2.2.3.jar"则提供了Quartz框架的实现,使得我们可以方便地在...
总的来说,Spring 与 Quartz 的整合提供了强大的定时任务管理能力,无论是旧版的 1.8 还是新版的 2.2,都可以帮助开发者灵活地定义和控制任务执行。理解并掌握这两个版本的整合方法,将有助于在实际开发中构建出稳定...
总的来说,"quartz-2.2.3-sql.zip"文件为开发者提供了在各种常见数据库上快速启动和配置Quartz的工具,使得任务调度的实现更加便捷和高效。无论是小型项目还是大型企业级应用,Quartz都能作为强大的定时任务管理工具...
Quartz 2.2.3 版本是这个框架的一个稳定版本,提供了许多改进和功能,以帮助开发人员更好地管理和调度任务。 文档部分包含了Quartz的详细使用指南、API参考以及示例,这些内容对于理解Quartz的工作原理和如何在项目...
总的来说,Quartz 2.2.3版本的jar包集合为开发者提供了一套强大的工具,用于创建和管理各种定时任务。无论是简单的后台操作还是复杂的业务逻辑,都可以借助Quartz实现自动化和智能化的调度。使用这个最新版本,...
总之,Quartz-2.2.3是一个强大且灵活的定时任务框架,它能帮助开发者轻松地管理和执行复杂的定时任务,提升应用程序的自动化程度。在实际项目中,结合合适的配置和定制化开发,可以极大地提高工作效率。
Quartz是Java领域的一款强大的开源任务调度框架,用于在应用程序中执行定时和计划的任务。它的最新版本为2.2.3,提供了丰富的功能和灵活性,适用于各种规模的应用。这个压缩包"quartz-2.2.3.jar"包含了实现分时作业...
总之,Quartz 2.2.3 为开发者提供了一套强大且灵活的任务调度工具,无论是简单定时任务还是复杂的业务流程,都可以借助 Quartz 实现高效自动化。通过深入学习和实践,我们可以充分利用其特性,提升应用程序的自动化...
标题中的"spring-context-support-4.2.2和quartz-2.2.3所需Jar包"涉及到两个关键的Java库:Spring Context Support 4.2.2版本和Quartz Scheduler 2.2.3版本。这两个库在企业级Java应用开发中扮演着重要角色,特别是...
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用...
Quartz是一个完全由java编写的开源作业调度框架,说人话就是你可以创建一些任务,规定这些任务什么时候执行、执行几次等。quartz-2.2.3-Jar包,经测试只需要引入quartz-2.2.3.jar、quartz-jobs-2.2.3.jar和slf4j-api...
在"quartz-2.2.3.jar"这个完整包中,包含了Quartz库的所有必要组件,以及示例源码、开发文档和其他相关联的jar包,这对于理解和使用Quartz进行任务调度非常有帮助。 1. **Quartz核心概念**: - **Job**:代表一个...