quartz api地址:http://www.quartz-scheduler.org/api/2.2.0/
根据需求选择quartz调度方案:
1,如果调度时间是固定不变的,可以选择静态调度
2,如果调度时间是可变的,可以选择动态调度,即通过配置时间参数或cron表达式实现调度变化。
静态调度方案:
spring 整合quartz
打开web.xml,添加加载路径
classpath*:spring-quartz.xml初始化上下文。
<servlet> <servlet-name>baseDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:servlet-context.xml,classpath*:spring-cas.xml,classpath*:spring-quartz.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
写具体的定时调度的任务:
package cn.com.base.quartz.invoke; public class SchedulerT_Log { public void schedulerT_Log() { System.out.println("使用quartz实现调度"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 添加调度的任务bean 配置对应的class--> <bean id="SchedulerT_Log" class="cn.com.base.quartz.invoke.SchedulerT_Log" /> <!--配置调度具体执行的方法--> <bean id="myPrintDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="SchedulerT_Log" /> <property name="targetMethod" value="schedulerT_Log" /> <property name="concurrent" value="false" /> </bean> <!--配置调度执行的触发的时间--> <bean id="myPrintTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> <property name="jobDetail" ref="myPrintDetail" /> <property name="cronExpression"> <value>0 0/30 * * * ?</value> </property> </bean> <!-- quartz的调度工厂 调度工厂只能有一个,多个调度任务在list中添加 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <!-- 所有的调度列表--> <!-- <ref local="sendNoticeTrigger" /> --> <!-- <ref local="timeOutNoticeTrigger" /> --> <!-- <ref local="beforeExpireNoticeTrigger" /> --> <ref local="myPrintTrigger" /> </list> </property> </bean> </beans>
注意
Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。
在Spring中如果使用 MethodInvokingJobDetailFactoryBean,可以通过设置concurrent="false"属性, 禁止并发执行。
|
<property name="concurrent"value="true"/> 动态调度方案: |
导入quartz.jar包,或者pom.xml 配置对应的依赖
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> </dependency> <version>2.2.1<ersion> <dependency> <artifactId>quartz-jobs</artifactId> <groupId>org.quartz-scheduler</groupId> <version>2.2.1<ersion> </dependency>
根据页面参数对象进行参数赋值转换,TaskContextParm是自定义的作业上下文参数对象,在这里特别注意org.quartz.CronExpression.isValidExpression(expression),该方法可以判断我们填写的cron表达式是否可以解析为一个有效的Cron表达式。这里由于页面有时间配置和填写cron表达式两种方式,在参数转换这里解耦。
@Override @Transactional public void scheduler(Scheduler scheduler) throws SchedulerException { TaskContextParam taskContextParam = new TaskContextParam(); try { taskContextParam.setJobname(scheduler.getJobName()); taskContextParam.setTriggername(scheduler.getName()); Integer cycletype = scheduler.getCycletype(); if(cycletype==2){ boolean rs = CronExpression.isValidExpression(scheduler.getExpression()); if(rs){ taskContextParam.setCronexpression(scheduler.getExpression()); } else{ return false; } }else{ taskContextParam.setFlag(scheduler.getCycle()); if (scheduler.getMinute() != null) { taskContextParam.setMinute(scheduler.getMinute()); } if(scheduler.getHour() != null) { taskContextParam.setHour(scheduler.getHour()); } if(scheduler.getWeekly() != null) { taskContextParam.setWeekly(scheduler.getWeekly()); } if (scheduler.getMonth() != null) { taskContextParam.setMonth(scheduler.getMonth()); } } new SchedulerManager().addSchedulerJob(taskContextParam); } catch (SchedulerException e) { e.printStackTrace(); } }
SchedulerManager.java
public void addSchedulerJob(TaskContextParam taskContextParam) throws SchedulerException { JobDetail job = null; Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); job = JobBuilder.newJob(ExeKtrJob.class) .withIdentity(taskContextParam.getJobname(), "group1") .usingJobData(ConstantManager.FILE_ID,taskContextParam.getId()) .usingJobData(ConstantManager.FILE_TYPE,ConstantManager.FILE_TYPE_ID) .build(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity(taskContextParam.getTriggername(), "group1") .startNow() .withSchedule(setScheduleBuilderWithTime(taskContextParam)) .build(); scheduler.scheduleJob(job, trigger); }
private ScheduleBuilder setScheduleBuilderWithTime(TaskContextParam taskContextParam) { if(taskContextParam.getCronexpression()!=null){ String cronExpression = taskContextParam.getCronexpression(); ScheduleBuilder<CronTrigger> cronSchedule = CronScheduleBuilder.cronSchedule(cronExpression); return cronSchedule; } else{ switch (Integer.parseInt(taskContextParam.getFlag())) { case 1:// 每隔多少分钟 return simpleSchedule().withIntervalInMinutes( taskContextParam.getMinute()).repeatForever(); case 2:// 每隔多少小时 return simpleSchedule().withIntervalInMinutes( taskContextParam.getHour() * 60).repeatForever(); case 3:// 每天定点运行,格式 15:10 return dailyAtHourAndMinute(taskContextParam.getHour(), taskContextParam.getMinute()); case 4:// 每星期定点运行,格式 每星期三15:10 return weeklyOnDayAndHourAndMinute(taskContextParam.getWeekly(), taskContextParam.getHour(), taskContextParam.getMinute()); case 5:// 每月定点运行,格式 每月5号15:10 return monthlyOnDayAndHourAndMinute(taskContextParam.getMonth(), taskContextParam.getHour(), taskContextParam.getMinute()); default: return null; } } }
ExeKtrJob.java
public class ExeKtrJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { Timestamp scheduledFireTime = new java.sql.Timestamp(context.getScheduledFireTime().getTime()); Timestamp previousFireTime = null; if(context.getPreviousFireTime()!=null){ previousFireTime = new java.sql.Timestamp(context.getPreviousFireTime().getTime()); } Timestamp nextFireTime = new java.sql.Timestamp(context.getNextFireTime().getTime()); String fireInstanceId = context.getFireInstanceId(); Trigger trigger = context.getTrigger(); String jobname = trigger.getJobKey().getName(); String triggername = trigger.getKey().getName(); JobDataMap jobDataMap = context.getMergedJobDataMap(); String fileType=(String) jobDataMap.get(ConstantManager.FILE_TYPE); int id=Integer.parseInt((String) jobDataMap.get(ConstantManager.FILE_ID)); } }