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实现调度");
}
}
创建调度配置文件spring-quartz.xml
<?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));
}
}