spring 09-Spring框架基于QuartZ实现调度任务

java定时调度任务

  • 定时调度:在无人值守的时候后,系统可在某一时刻执行某些特定功能的机制
  • 定时调度操作分为两种:定时触发、间隔触发
  • java提供两个定时调度处理类:Timer、TimerTask
  • TimerTask主要是定义任务执行,相当于启动一个线程执行某些任务的处理
  • 企业项目开发过程中基本使用两种定时控制的选择
    • quartz组件:企业级定时处理调度组件,需要单独配置
    • Spring Task:轻量级组件,配置简单,可以利用Annotation实现配置处理

编写任务程序:

package cn.liang.forget;
import java.text.SimpleDateFormat;
import java.util.TimerTask;
public class TaskDemo01 extends TimerTask {	
	@Override
	public void run() {
		System.out.println("【当前日期时间】" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
	}
}

编写间隔触发程序:

package cn.liang.test;
import java.util.Timer;
import cn.liang.forget.TaskDemo01;
public class TaskTest01 {
	public static void main(String[] args) {
		Timer timer = new Timer();
		//间隔触发
		timer.schedule(new TaskDemo01(),0,1000);
	}
}

输出结果:

【当前日期时间】2018-12-04 11:36:03.617
【当前日期时间】2018-12-04 11:36:04.574
【当前日期时间】2018-12-04 11:36:05.578
【当前日期时间】2018-12-04 11:36:06.583
【当前日期时间】2018-12-04 11:36:07.586
【当前日期时间】2018-12-04 11:36:08.587
【当前日期时间】2018-12-04 11:36:09.589
【当前日期时间】2018-12-04 11:36:10.594
......

编写延迟触发程序:

package cn.liang.test;
import java.util.Timer;
import cn.liang.forget.TaskDemo01;
public class TaskTest01 {
	public static void main(String[] args) {
		Timer timer = new Timer();
		//延迟触发
		timer.schedule(new TaskDemo01(),2000);
	}
}

输出结果:

【当前日期时间】2018-12-04 11:38:58.211

QuartZ实现定时任务

  • QuartZ组件的开发过程有两种实现模式
    • 要求明确的去继承一个父类
    • 利用配置实现方法调度控制,不需要明确继承父类
  • 本次直接基于Spring的配置管理的方式来实现定时调度控制

导入QuartZ组件开发包,配置Maven的pom.xml文件

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>

继承QuartzJobBean父类实现定时任务

1、定义任务处理类

package cn.liang.forget;
import java.text.SimpleDateFormat;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class TaskDemo2 extends QuartzJobBean{
	@Override
	protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
		System.out.println("【当前日期时间】" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
	}
}

2、修改applicationContext.xml配置文件

  • 在整个的Spring容器里面注册已经配置好的任务调度类
<!-- 此处表示将要执行的任务控制类在Spring中进行注册,并且告诉容器,谁来执行具体的任务 -->
<bean id="taskFactory1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
	<!-- 当前可以执行任务的程序类,这个类就是QuartzJobBean的子类 -->
	<property name="jobClass" value="cn.liang.forget.TaskDemo2"/>
	<!-- 配置一次任务执行时所需要的若干配置信息 -->	
	<property name="jobDataMap">
		<map>	<!-- 任务启动之后立即执行 -->
			<entry key="timeout" value="0"/>
		</map>
	</property>
</bean>
  • 配置任务的触发作业的间隔触发
<!-- 描述的是间隔触发控制 -->
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
	<!-- 定义间隔触发的执行程序类 -->
	<property name="jobDetail" ref="taskFactory1"/>
	<!-- 定义的是是具体的触发的延迟时间,如果设置为0,表示立刻触发 -->
	<property name="startDelay" value="0"/>
	<!-- 间隔触发的频次,间隔时间单位为“毫秒” -->
	<property name="repeatInterval" value="2000"/>
</bean>
  • 设置任务的触发作业的间隔触发调度器
<!-- 定义调度工厂类的配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
			<ref bean="simpleTrigger"/> 
		</list>
	</property>
</bean>

启动Spring容器实现间隔触发任务,所有的间隔触发的控制操作都交由Spring管理

package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TaskTest2 {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
	}
}

输出结果:

2018-12-04 14:17:40,050 INFO [org.quartz.impl.StdSchedulerFactory] - Using default implementation for ThreadExecutor
2018-12-04 14:17:40,076 INFO [org.quartz.core.SchedulerSignalerImpl] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-04 14:17:40,076 INFO [org.quartz.core.QuartzScheduler] - Quartz Scheduler v.2.3.0 created.
2018-12-04 14:17:40,084 INFO [org.quartz.simpl.RAMJobStore] - RAMJobStore initialized.
2018-12-04 14:17:40,085 INFO [org.quartz.core.QuartzScheduler] - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

2018-12-04 14:17:40,086 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
2018-12-04 14:17:40,086 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler version: 2.3.0
2018-12-04 14:17:40,088 INFO [org.quartz.core.QuartzScheduler] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@5bfa9431
2018-12-04 14:17:40,142 INFO [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2018-12-04 14:17:40,142 INFO [org.quartz.core.QuartzScheduler] - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
【当前日期时间】2018-12-04 14:17:40.175
【当前日期时间】2018-12-04 14:17:41.955
【当前日期时间】2018-12-04 14:17:43.956
【当前日期时间】2018-12-04 14:17:45.956
【当前日期时间】2018-12-04 14:17:47.956
......

QuartZ使用Cron实现定时触发

  • QuartZ最大的优势是可以结合cron表达式实现定时触发
  • cron服务器可以根据配置文件在约定的时间来执行特定的任务

cron表达式是一个字符串

  • seconds minutes hours day month week year
  • seconds:表示秒,可以是从0到59之间的任何整数。
  • minutes: 表示分钟,可以是从0到59之间的任何整数。
  • hours:表示小时,可以是从0到23之间的任何整数。
  • day:表示日期,可以是从1到31之间的任何整数。
  • month:表示月份,可以是从1到12之间的任何整数或JAN-DEC范围。
  • week:表示星期几,可以是从1到7之间的任何整数或SUN-SAT范围,这里的1代表星期日。
  • year:表示年,有效范围为1970-2099年

cron表达式作用域的含义

  • * :表示匹配该域的任意值,假如在minutes域使用*则表示每分钟都会触发事件
  • ? :只能用在day和week两个域上
  • - :表示范围,如果在minutes域使用5-20则表示从5分到20分内,每分钟触发一次
  • / :表示起始时间开始触发,然后每隔固定时间触发一次
  • , :表示列出枚举值
  • L :表示最后,只能用在day和week两个域上,如在week域使用5L则表示最后一个星期四触发
  • W :表示有效工作日(周一到周五),只能出现day域
  • # :表示确认每个月的第几个星期几,只能出现day域,如4#2表示某月的第二个星期三

cron表达式举例

  • 0 0 2 1 * ? * :表示在每月的1日的凌晨2点调度任务
  • 0 15 10 ? * MON-FRI :表示周一到周五每天上午10:15执行作业
  • 0 15 10 ? * 6L 2018-2030 :表示2018-2030年的每个月的最后一个星期五上午10:15执行作业
  • 0 0 10,14,16 * * ? :表示每天上午10点,下午2点、4点
  • 0 0/30 9-17 * * ? :表示9点到17点工作时间内每半小时
  • 0 0 12 ? * WED :表示每个星期三中午12点
  • 0 0 12 * * ? :表示每天中午12点触发
  • 0 15 10 ? * * :表示每天10:15触发
  • 0 15 10 * * ? :表示每天10:15触发
  • 0 15 10 * * ? 2005 :表示2005年的每天10:15触发
  • 0 * 14 * * ? :表示每天14点到14:59分期间,每1分钟触发
  • 0 0/5 14 * * ? :表示每天14点到14:55分期间,每5分钟触发
  • 0 0/5 14,18 * * ? :表示每天14点到14:55分和18点到18:55分期间,每5分钟触发
  • 0 0-5 14 * * ? :表示每天14点到14:05分期间,每1分钟触发
  • 0 10,44 14 ? 3 WED :表示每年三月的星期三的14:10和14:44触发
  • 0 15 10 ? * MON-FRI :表示周一到周五的10:15触发

修改applicationContext.xml配置文件,使用间隔控制类进行定时触发处理

<bean id="taskFactory1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
	<property name="jobClass" value="cn.liang.forget.TaskDemo2"/>
	<property name="jobDataMap">
		<map>
			<entry key="timeout" value="0"/>
		</map>
	</property>
</bean>

<!-- 使用定时触发处理 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	<!-- 定义间隔触发的执行程序类 -->
	<property name="jobDetail" ref="taskFactory1"/>
	<!-- 定义CRON表达式,描述的是每分钟触发一次 -->
	<property name="cronExpression" value="0 * * * * ?"/>
</bean>

<!-- 定义调度工厂类的配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
			<ref bean="cronTrigger"/> 
		</list>
	</property> 
</bean>

启动Spring容器实现间隔触发任务,所有的间隔触发的控制操作都交由Spring管理

package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TaskTest2 {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
	}
}

输出结果:

2018-12-04 15:13:07,113 INFO [org.quartz.impl.StdSchedulerFactory] - Using default implementation for ThreadExecutor
2018-12-04 15:13:07,129 INFO [org.quartz.core.SchedulerSignalerImpl] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-04 15:13:07,129 INFO [org.quartz.core.QuartzScheduler] - Quartz Scheduler v.2.3.0 created.
2018-12-04 15:13:07,130 INFO [org.quartz.simpl.RAMJobStore] - RAMJobStore initialized.
2018-12-04 15:13:07,131 INFO [org.quartz.core.QuartzScheduler] - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

2018-12-04 15:13:07,131 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
2018-12-04 15:13:07,131 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler version: 2.3.0
2018-12-04 15:13:07,132 INFO [org.quartz.core.QuartzScheduler] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@5bfa9431
2018-12-04 15:13:07,152 INFO [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2018-12-04 15:13:07,153 INFO [org.quartz.core.QuartzScheduler] - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
【当前日期时间】2018-12-04 15:14:00.021
【当前日期时间】2018-12-04 15:15:00.004

QuartZ通过配置自动实现调度

  • 由于QuartZ的调用需要继承QuartzJobBean父类,容易导致单继承的局限控制
  • 因此Spring提供了不继承任何类实现的定时处理操作任务

定义一个处理任务的执行类

package cn.liang.forget;
import java.text.SimpleDateFormat;
public class TaskDemo3{
	public void task(){
		System.out.println("【当前日期时间】" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new java.util.Date()));
	}
}

修改applicationContext.xml配置文件

<!-- 配置自定义的任务执行类操作 -->
<bean id="taskFactory2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
	<!-- 定义要执行任务调度的任务类对象,需要一个具体的对象处理 -->
	<property name="targetObject">
		<bean class="cn.liang.forget.TaskDemo3"/>
	</property>
	<!-- 定义任务执行的时候所调用的操作方法名称 -->
	<property name="targetMethod" value="task"/>
</bean> 

<!-- 使用定时触发处理 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
	<!-- 定义间隔触发的执行程序类 -->
	<property name="jobDetail" ref="taskFactory2"/>
	<!-- 定义CRON表达式,描述的是每分钟触发一次 -->
	<property name="cronExpression" value="0 * * * * ?"/>
</bean>

<!-- 定义调度工厂类的配置 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
	<property name="triggers">
		<list>
			<ref bean="cronTrigger"/> 
		</list>
	</property> 
</bean>

启动Spring容器实现间隔触发任务,所有的间隔触发的控制操作都交由Spring管理

package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TaskTest2 {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
	}
}

输出结果:

2018-12-04 15:35:59,257 INFO [org.quartz.impl.StdSchedulerFactory] - Using default implementation for ThreadExecutor
2018-12-04 15:35:59,269 INFO [org.quartz.core.SchedulerSignalerImpl] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2018-12-04 15:35:59,270 INFO [org.quartz.core.QuartzScheduler] - Quartz Scheduler v.2.3.0 created.
2018-12-04 15:35:59,270 INFO [org.quartz.simpl.RAMJobStore] - RAMJobStore initialized.
2018-12-04 15:35:59,271 INFO [org.quartz.core.QuartzScheduler] - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

2018-12-04 15:35:59,271 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' initialized from an externally provided properties instance.
2018-12-04 15:35:59,271 INFO [org.quartz.impl.StdSchedulerFactory] - Quartz scheduler version: 2.3.0
2018-12-04 15:35:59,272 INFO [org.quartz.core.QuartzScheduler] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@7995092a
2018-12-04 15:35:59,306 INFO [org.springframework.scheduling.quartz.SchedulerFactoryBean] - Starting Quartz Scheduler now
2018-12-04 15:35:59,306 INFO [org.quartz.core.QuartzScheduler] - Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED started.
【当前日期时间】2018-12-04 15:36:00.024
【当前日期时间】2018-12-04 15:37:00.005
【当前日期时间】2018-12-04 15:38:00.003
原文地址:https://www.cnblogs.com/liangjingfu/p/10065146.html