在各种企业应用中经常遇到任务调度的需求,Sun JDK 本身提供的java.util.Timer和TimerTask提供了简单的调度功能,允许用户按照一个固定的时间间隔,周期运行任务。Quartz是开源任务调度运用最为广泛的框架,它提供了强大的任务调度机制,允许开发人员灵活地定义触发器的调度时间表,对触发器和任务进行关联映射,并且Quartz提供了调度运行环境的持久化机制,可以保存并恢复调度现场。
1)Quartz中的一些核心概念
Job:一接口,只有一个void excute (JobExecutionContext context) 方法,开发者可以通过实现该接口来定义运行任务,context提供了上下文的各种信息。
JobDetail:接收一个Job实现类,在运行时通过newInstance()的反射机制实例化Job。
Trigger:描述触发Job执行的时间触发规则。有SimpleTrigger和CronTrigger两个子类,其中CronTrigger定义更为灵活,通过Cron表达式定义各种复杂时间规则的调度方案。
Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail在Scheduler中注册,两者在Scheduler中拥有各自的组与名称,Trigger的组和名称必须唯一,JobDetail的组和名称也必须唯一。
2)在Spring中集成Quartz
Spring为创建Quartz的Scheduler、Trigger和JobDetail提供了便利的FactoryBean类以便在Spring容器中使用依赖注入的优点,此外Spring提供工具类可以直接将Spring中的Bean包装成合法的任务(Spring提供了一个MethodInvokingJobDetailFactoryBean,通过这个FactoryBean类可以将Spring容器中的Bean包装成Quartz任务),Spring进一步降低了Quartz的使用难度。
3)一个简单的Demo
a. 新建一Web项目,带入所需的Quartz包和Spring包,项目目录如图-1所示:
图-1
b. 配置web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:/applicationContext.xml</param-value>
- </context-param>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.util.IntrospectorCleanupListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.context.request.RequestContextListener
- </listener-class>
- </listener>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
c. 配置applicationContext.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"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
- <bean id="MyJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
- <property name="jobClass" value="com.demo.quartz.MyJob"/>
- <property name="jobDataAsMap">
- <map>
- <entry key="size" value="10"></entry>
- </map>
- </property>
- <property name="applicationContextJobDataKey" value="applicationContext"/>
- </bean>
- <bean id="MyJobScheduledTask" class="org.springframework.scheduling.quartz.CronTriggerBean">
- <property name="jobDetail" ref="MyJobDetail"/>
- <property name="cronExpression" value="0 19 10 6 * ? *"></property>
- </bean>
- <bean id="HiJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
- <property name="jobClass" value="com.demo.quartz.HiJob"/>
- <property name="jobDataAsMap">
- <map>
- <entry key="size" value="10"></entry>
- </map>
- </property>
- <property name="applicationContextJobDataKey" value="applicationContext"/>
- </bean>
- <bean id="HiJobScheduledTask" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
- <property name="startDelay" value="10000"/>
- <property name="repeatInterval" value="2000"/>
- <property name="jobDetail" ref="HiJobDetail"/>
- </bean>
- <bean id="QuartzJobFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="triggers">
- <list>
- <ref bean="MyJobScheduledTask"/>
- <!-- <ref bean="HiJobScheduledTask"/> -->
- </list>
- </property>
- <!-- 设置是否Spring容器初始化后马上启动Scheduler,默认为true。如果设置为false则需要手工启动Scheduler -->
- <property name="autoStartup" value="true"/>
- </bean>
- </beans>
d. HiJob类
- package com.demo.quartz;
- import java.util.Date;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- public class HiJob implements Job {
- public void execute(JobExecutionContext context)
- throws JobExecutionException {
- System.out.println("This is HiJob, Run time is " + new Date());
- }
- }
- package com.demo.quartz;
- import java.util.Date;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- public class MyJob implements Job {
- public void execute(JobExecutionContext context)
- throws JobExecutionException {
- System.out.println("This is MyJob, Run time is " + new Date());
- }
- }
f. Client测试类
- package com.demo.quartz;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Client {
- /**
- * @param args
- */
- public static void main(String[] args) {
- ApplicationContext context =
- new ClassPathXmlApplicationContext("applicationContext.xml");
- Scheduler a = (Scheduler) context.getBean("QuartzJobFactory");
- try {
- a.start();
- } catch (SchedulerException e) {
- e.printStackTrace();
- }
- }
- }
在Spring中集成Quartz极大地方便了任务调度功能的实现,并且通过SchedulerFactoryBean能够和Spring容器的生命周期关联,在Spring容器启动时,启动调度器。
e. MyJob类