Quartz
Quartz是一个完全由java编写的开源作业调度框架.
Quartz最主要的功能就是调度器(完成定时任务),可以与javaEE或者javaSE应用程序相结合也可以单独使用。
Quartz能借助关系数据库和JDBC作业存储支持集群,负载均衡。
Spring Quartz
Spring中继承并简化了Quartz, 我们可以通过配置Spring简化Quartz的配置。
在ApplicationContext.xml配置数据源,并且引入ApplicationContext-quartz.xml文件。
ApplicationContext.xml:
- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
- <property name="jndiName" value="java:comp/env/jdbc/publicdb"></property>
- </bean>
- .
- .
- .
- .
- <!-- import -->
- <import resource="ApplicationContext-quartz.xml" />
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/publicdb"></property> </bean> . . . . <!-- import --> <import resource="ApplicationContext-quartz.xml" />
ApplicationContext-quartz.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans default-autowire="byName">
- <!-- 要调用的工作类 -->
- <bean id="reportCreateJob" class="org.quartz.JobDetail">
- <property name="jobClass">
- <value>com.hundsun.u3c.reportserver.quartz.job.ReportCreateJob</value>
- </property>
- <property name="name" value="reportCreate-processor-job" />
- </bean>
- <!-- 定义触发时间 -->
- <bean id="reportCreateTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
- <property name="jobDetail">
- <ref bean="reportCreateJob" />
- </property>
- <property name="cronExpression">
- <value>0 * * * * ?</value>
- </property>
- </bean>
- <!-- 管理类:配置Schedule信息,与spring容器的生命周期建立联系等功能 -->
- <bean id="scheduler"
- class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <!-- 在SchedulerFactoryBean初始化完成后,延迟300秒启动Scheduler,以便让Spring能够更快初始化容器中剩余的Bean。-->
- <property name="startupDelay" value="300" />
- <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
- <property name="quartzProperties">
- <props>
- <prop key="org.quartz.scheduler.instanceName">qmsQuartzScheduler</prop>
- <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
- <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
- <prop key="org.quartz.threadPool.threadCount">3</prop>
- <prop key="org.quartz.threadPool.threadPriority">5</prop>
- <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
- <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
- <prop key="org.quartz.jobStore.driverDelegateClass">${QUARTZ_DRIVERDELEGATECLASS}</prop>
- <prop key="org.quartz.jobStore.selectWithLockSQL">SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?</prop>
- <prop key="org.quartz.jobStore.tablePrefix">U3C_QRTZ_</prop>
- <prop key="org.quartz.jobStore.isClustered">true</prop>
- <prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
- </props>
- </property>
- <!-- scheduler by QuartzAdjust -->
- <property name="triggers">
- <list>
- <ref bean="reportCreateTrigger" />
- </list>
- </property>
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<!-- 要调用的工作类 -->
<bean id="reportCreateJob" class="org.quartz.JobDetail">
<property name="jobClass">
<value>com.hundsun.u3c.reportserver.quartz.job.ReportCreateJob</value>
</property>
<property name="name" value="reportCreate-processor-job" />
</bean>
<!-- 定义触发时间 -->
<bean id="reportCreateTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="reportCreateJob" />
</property>
<property name="cronExpression">
<value>0 * * * * ?</value>
</property>
</bean>
<!-- 管理类:配置Schedule信息,与spring容器的生命周期建立联系等功能 -->
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 在SchedulerFactoryBean初始化完成后,延迟300秒启动Scheduler,以便让Spring能够更快初始化容器中剩余的Bean。-->
<property name="startupDelay" value="300" />
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">qmsQuartzScheduler</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">3</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">${QUARTZ_DRIVERDELEGATECLASS}</prop>
<prop key="org.quartz.jobStore.selectWithLockSQL">SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?</prop>
<prop key="org.quartz.jobStore.tablePrefix">U3C_QRTZ_</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
</props>
</property>
<!-- scheduler by QuartzAdjust -->
<property name="triggers">
<list>
<ref bean="reportCreateTrigger" />
</list>
</property>
</bean>
</beans>
JobDetail: 可以使用Quartz的JobDetail在Spring中配置一个JobDetail Bean,但是JobDetail使用带参的构造函数。[public void execute(JobExecutionContext arg0)]
也可以使用JobDetailBean,Spring通过扩展JobDetail提供了一个更具Bean风格的JobDetailBean。此外,Spring提供了一个MethodInvokingJobDetailFactoryBean,通过这个FactoryBean可以将Spring容器中Bean的方法包装成Quartz任务,这样开发者就不必为Job创建对应的类。
CronTriggerBean调度器:每到指定时间则触发一次。与之相对的还有SimpleTriggerBean调度器,每隔指定时间则触发一次。
属性解释:
1.jobDetail:对应的JobDetail.
2.cronExpression:Cron表达式,后面详解。
SchedulerFactoryBean是Spring继承Quartz而提供的类。
Scheduler和Spring容器的生命周期相关联。Spring容器启动后,Scheduler自动开始工作,而在Spring容器关闭前,自动关闭Scheduler。Scheduler在Spring容器的生命周期完成自动启动和关闭的操作。
SchedulerFactoryBean功能:
1.以更具Bean风格的方式为Scheduler提供配置信息。
2.让Scheduler和Spring容器的生命周期建立关联,相生相息。
3.通过属性配置部分或全部代替Quartz自身的配置文件。
参数解释:
1.dataSource: 当需要使用数据库来持久化任务调度数据时,你可以在Quartz中配置数据源,也可以直接在Spring中通过dataSource指定一个Spring管理的数据源。如果指定了该属性,即使quartz.properties中已经定义了数据源,也会被此dataSource覆盖。
2.startupDelay:在SchedulerFactoryBean初始化完成后,延迟启动Scheduler,以便让Spring能够更快初始化容器中剩余的Bean。
3.quartzProperties:类型为Properties,允许你在Spring中定义Quartz的属性。其值将覆盖quartz.properties配置文件中的设置,这些属性必须是Quartz能够识别的合法属性。在配置时你可以需要查看Quartz的相关文档。
4.transactionManager:可以通过该属性设置一个Spring事务管理器。在设置dataSource时,Spring强烈推荐你使用一个事务管理器,否则数据表锁定可能不能正常工作。
JobDetailBean:
- * @author jiangbo
- *
- */
- public class ReportCreateJob implements StatefulJob {
- private static Logger log = Logger.getLogger(ReportCreateJob.class);
- @Override
- public void execute(JobExecutionContext arg0) throws JobExecutionException {
- log.debug("===into quartz job =======>");
- ReportCreateBusiness.getInstance().createReport();
- }
- }
* @author jiangbo
*
*/
public class ReportCreateJob implements StatefulJob {
private static Logger log = Logger.getLogger(ReportCreateJob.class);
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
log.debug("===into quartz job =======>");
ReportCreateBusiness.getInstance().createReport();
}
}
Quartz的集群配置
org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。
org.quartz.scheduler.instanceId属性为AUTO即可,基于主机名和时间戳来产生实例ID。
org.quartz.jobStore.isClustered设置为"true"激活集群特性
org.quartz.jobStore.class属性为JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播Scheduler实例的状态,你只能在使用JDBC JobStore时应用Quartz集群。这意味着你必须使用JobStoreTX或是JobStoreCMT作为Job存储。你不能在集群中使用RAMJobStore。
org.quartz.jobStore.clusterCheckinInterval属性定义了Scheduler实例检入到数据库中的频率(单位:毫秒)。Scheduler检查是否其他的实例到了它们应当检入的时候未检入。这能指出一个失败的Scheduler实例,且当前 Scheduler会以此来接管任何执行失败并可恢复的Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval越小,Scheduler节点检查失败的Scheduler实例就越频繁。默认值是15000 (即15秒)。
dataSource:项目中用到的数据源,里面包含了quartz用到的12张数据库表。
applicationContextSchedulerContextKey:org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文.
configLocation:用于指明quartz的配置文件的位置.
Quartz集群12张表:
表名 | 描述 |
QRTZ_CALENDARS | 以Blob类型存储Quartz的Calendar信息. |
QRTZ_CRON_TRIGGERS | 存储Cron Trigger,包括Cron表达式和时区信息. |
QRTZ_FIRED_TRIGGERS | 存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息. |
QRTZ_PAUSED_TRIGGER_GRPS | 存储已暂停的Trigger组的信息。 |
QRTZ_SCHEDULER_STATE | 存储少量的有关Scheduler的状态信息,和别的cheduler 实例(假如是用于一个集群中) |
QRTZ_LOCKS | 存储程序的非观锁的信息(假如使用了悲观锁)。 |
QRTZ_JOB_DETAILS | 存储每一个已配置的Job的详细信息。 |
QRTZ_JOB_LISTENERS | 存储有关已配置的JobListener的信息。 |
QRTZ_SIMPLE_TRIGGERS | 存储简单的Trigger,包括重复次数,间隔,以及已触的次数。 |
QRTZ_BLOG_TRIGGERS | Trigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore并不知道如何存储实例的时候) |
QRTZ_TRIGGER_LISTENERS | 存储已配置的TriggerListener的信息. |
QRTZ_TRIGGERS | 存储已配置的Trigger的信息. |
QRTZ_TRIGGERS表中TRIGGER_STATE字段显示任务的属性:
WAITING:等待
PAUSED:暂停
ACQUIRED:正常执行
BLOCKED:阻塞
ERROR:错误
Cron表达式
Quartz使用类似于Linux下的Cron表达式定义时间规则,Cron表达式由6或7个由空格分隔的时间字段组成。
Cron表达式时间字段:
位置 | 时间域名 | 允许值 | 允许的特殊字符 |
1 | 秒 | 0-59 | , - * / |
2 | 分钟 | 0-59 | , - * / |
3 | 小时 | 0-23 | , - * / |
4 | 日期 | 1-31 | , - * ? / L W C |
5 | 月份 | 1-12 | , - * / |
6 | 星期 | 1-7 | , - * ? / L C # |
7 | 年(可选) | 空值1970-2099 | , - * / |
Cron表达式示例:
表达式 | 说明 |
"0 0 12 * * ? " | 每天12点运行 |
"0 15 10 * * ?" | 每天10:15运行 |
"0 15 10 * * ? 2011" | 2011年的每天10:15运行 |
"0 * 14 * * ?" | 每天14点到15点之间每分钟运行一次,开始于14:00,结束于14:59。 |
"0 0/5 14 * * ?" | 每天14点到15点每5分钟运行一次,开始于14:00,结束于14:55。 |
"0 0/5 14,18 * * ?" | 每天14点到15点每5分钟运行一次,此外每天18点到19点每5钟也运行一次。 |
"0 0-5 14 * * ?" | 每天14:00点到14:05,每分钟运行一次。 |
"0 10,44 14 ? 3 WED" | 3月每周三的14:10分到14:44,每分钟运行一次。 |
"0 15 10 ? * MON-FRI" | 每周一,二,三,四,五的10:15分运行。 |
"0 15 10 15 * ?" | 每月15日10:15分运行。 |
"0 15 10 L * ?" | 每月最后一天10:15分运行。 |
"0 15 10 ? * 6L" | 每月最后一个星期五10:15分运行。 |
"0 15 10 ? * 6L 2007-2009" | 在2007,2008,2009年每个月的最后一个星期五的10:15分运行。 |
"0 15 10 ? * 6#3" | 每月第三个星期五的10:15分运行。 |