Spring与Quartz集成详解

首先这个所有的依赖包就不需要多讲了,首先下载Quazrt发布包,解压,运行doc文件夹下(E:\Quartz\quartz-2.2.3\docs\dbTables)的tables_mysql_innodb.sql脚本
新建job
//MyJob 普通job,这个不需要实现org.quartz.Job
package job;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyJob {
    Logger log = LoggerFactory.getLogger(MyJob.class);
    public void work () {
        // 此任务仅打印日志便于调试、观察
    	log.info("==================:"+this.getClass().getName() + " was just triggered...");
    }  
}

//MyQuartzJob,这个job因为我们要把job持久化到RDB所以要实现org.quartz.Job
package job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyQuartzJob implements Job{
	Logger log = LoggerFactory.getLogger(MyQuartzJob.class);
	@Override
	public void execute(JobExecutionContext jobexecutioncontext)
			throws JobExecutionException {
		log.info("==================:"+this.getClass().getName() + " was just triggered...");
	}
}

Spring与Quartz的集成配置
//SchedulerFactoryBean配置
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" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context   
    http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 调度工厂 -->
	<bean id="quartzScheduler"
		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="quartzProperties">
			<props>
				<prop key="org.quartz.scheduler.instanceName">defaultScheduler</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">20</prop>
				<prop key="org.quartz.threadPool.threadPriority">5</prop>
				<!-- JobStore配置 -->
				<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
				<!-- 集群配置 -->
				<prop key="org.quartz.jobStore.isClustered">true</prop>
				<prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop>
				<prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop>
				<prop key="org.quartz.jobStore.misfireThreshold">120000</prop>
				<!-- 表名配置 -->
				<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
			</props>
		</property>
		<property name="schedulerName" value="defaultScheduler" />
		<!-- 必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 -->
		<property name="startupDelay" value="30" />
		<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
		<!-- 可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 -->
		<property name="overwriteExistingJobs" value="true" />
		<!-- 设置自动启动 -->
		<property name="autoStartup" value="true" />
		<!-- 注册触发器 -->
		<property name="triggers">
			<ref bean="defaultTriggers" />
		</property>
		<!-- 注册jobDetail -->
		<property name="jobDetails">
			<ref bean="defaultJobDetails" />
		</property>
		<!-- 注册监听器 -->
		<property name="schedulerListeners">
			<ref bean="defaultSchedulerListeners" />
		</property>
	</bean>
	<import resource="quartz-task.xml" />
</beans>

//定时任务配置
quartz-task.xm
<?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:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd">
	<!-- 工作的bean -->
	<bean id="myJob" class="job.MyJob" />
	<!-- job的配置开始 -->
	<bean id="myJobDetail"
		class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="myJob" />
		<property name="targetMethod" value="work" />
		<!-- <property name="concurrent" value="false" /> -->
	</bean>
	<bean id="myQuartzJobDetail"
		class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass" value="job.MyQuartzJob" />
		<property name="name" value="myQuartzJob" />
		<!-- 任务完成之后是否依然保留到数据库,默认false -->
		<property name="durability" value="true" />
	</bean>
	<!-- job的配置结束 -->
	<!-- 调度任务配置开始 -->
	<bean id="cronTestJobTrigger"
		class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail" ref="myJobDetail" />
		<!-- Cron表达式“0/5 * * * * ?”意为:每5秒执行一次。 -->
		<property name="cronExpression" value="0/5 * * * * ?" />
	</bean>
	<bean id="cronTestQuartzJobTrigger"
		class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail" ref="myQuartzJobDetail" />
		<property name="cronExpression" value="0/5 * * * * ?" />
	</bean>
	<!-- 默认调度器(defaultScheduler)触发器配置 -->
	<util:list id="defaultTriggers">
		<!-- <ref bean="crontestJobTrigger"/> -->
		<ref bean="cronTestQuartzJobTrigger" />
	</util:list>
	<!-- 默认调度器(defaultScheduler)Job实例配置 -->
	<util:list id="defaultJobDetails">
	</util:list>
	<!-- 默认调度器(defaultScheduler)监听器配置 -->
	<util:list id="defaultSchedulerListeners">
	</util:list>
	<!-- JobDetail-配置示例 -->
	<!-- <bean id="demoJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> 
			<property name="jobClass" value="job.MyQuartzJob" /> 
			<property name="jobDataAsMap"> 
				<map> 
					<entry key="key" value="value" /> 
				</map>
			</property>
		 </bean> -->
</beans>

启动web控制台输出:
信息: Server startup in 11783 ms
2016-09-09 17:44:00 -32594 [org.springframework.scheduling.quartz.SchedulerFactoryBean] INFO    - Starting Quartz Scheduler now, after delay of 30 seconds
2016-09-09 17:44:00 -32660 [org.quartz.core.QuartzScheduler] INFO    - Scheduler defaultScheduler_$_donaldHP1473414210553 started.
2016-09-09 17:44:01 -32758 [job.MyQuartzJob] INFO    - ==================:job.MyQuartzJob was just triggered...
2016-09-09 17:44:01 -32802 [job.MyQuartzJob] INFO    - ==================:job.MyQuartzJob was just triggered...
2016-09-09 17:44:01 -32842 [job.MyQuartzJob] INFO    - ==================:job.MyQuartzJob was just triggered...
查看数据库Quartz,job,trriger相关信息:
mysql> use test;
Database changed
mysql> select * from qrtz_cron_triggers;
+------------------+--------------------------+---------------+-----------------+---------------+
| SCHED_NAME       | TRIGGER_NAME             | TRIGGER_GROUP | CRON_EXPRESSION | TIME_ZONE_ID  |
+------------------+--------------------------+---------------+-----------------+---------------+
| defaultScheduler | cronTestQuartzJobTrigger | DEFAULT       | 0/5 * * * * ?  | Asia/Shanghai |
+------------------+--------------------------+---------------+-----------------+---------------+
1 row in set

mysql> select * from qrtz_fired_triggers;
+------------------+------------------------------------+--------------------------+---------------+-----------------------+---------------+---------------+----------+----------+----------+-----------+------------------+-------------------+
| SCHED_NAME       | ENTRY_ID                           | TRIGGER_NAME             | TRIGGER_GROUP | INSTANCE_NAME         | FIRED_TIME    | SCHED_TIME    | PRIORITY | STATE    | JOB_NAME | JOB_GROUP | IS_NONCONCURRENT | REQUESTS_RECOVERY |
+------------------+------------------------------------+--------------------------+---------------+-----------------------+---------------+---------------+----------+----------+----------+-----------+------------------+-------------------+
| defaultScheduler | donaldHP14734142105531473414210556 | cronTestQuartzJobTrigger | DEFAULT       | donaldHP1473414210553 | 1473414385029 | 1473414390000 |        0 | ACQUIRED | NULL     | NULL      | 0                | 0                 |
+------------------+------------------------------------+--------------------------+---------------+-----------------------+---------------+---------------+----------+----------+----------+-----------+------------------+-------------------+
1 row in set

mysql> select * from qrtz_triggers;
+------------------+--------------------------+---------------+-------------+-----------+-------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+----------+
| SCHED_NAME       | TRIGGER_NAME             | TRIGGER_GROUP | JOB_NAME    | JOB_GROUP | DESCRIPTION | NEXT_FIRE_TIME | PREV_FIRE_TIME | PRIORITY | TRIGGER_STATE | TRIGGER_TYPE | START_TIME    | END_TIME | CALENDAR_NAME | MISFIRE_INSTR | JOB_DATA |
+------------------+--------------------------+---------------+-------------+-----------+-------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+----------+
|defaultScheduler | cronTestQuartzJobTrigger | DEFAULT       | myQuartzJob | DEFAULT   | NULL        |  1473414390000 |  1473414385000 |        0 | ACQUIRED      | CRON         | 1473414210000 |        0 | NULL          |             0 |          |
+------------------+--------------------------+---------------+-------------+-----------+-------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+----------+
1 row in set

mysql> select * from qrtz_job_details;
+------------------+-------------+------------------+-------------+-----------------+------------+------------------+----------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SCHED_NAME       | JOB_NAME    | JOB_GROUP        | DESCRIPTION | JOB_CLASS_NAME  | IS_DURABLE | IS_NONCONCURRENT | IS_UPDATE_DATA | REQUESTS_RECOVERY | JOB_DATA                                                                          

| defaultScheduler | myQuartzJob | DEFAULT          | NULL        | job.MyQuartzJob | 1          | 0                | 0              | 0                 | 
?
loadFactorI


mysql> select * from qrtz_locks;
+------------------+----------------+
| SCHED_NAME       | LOCK_NAME      |
+------------------+----------------+
| defaultScheduler | STATE_ACCESS   |
| defaultScheduler | TRIGGER_ACCESS |
+------------------+----------------+
2 rows in set

mysql> select * from qrtz_scheduler_state;
+------------------+-----------------------+-------------------+------------------+
| SCHED_NAME       | INSTANCE_NAME         | LAST_CHECKIN_TIME | CHECKIN_INTERVAL |
+------------------+-----------------------+-------------------+------------------+
| defaultScheduler | donaldHP1473414210553 |     1473414375985 |            15000 |
+------------------+-----------------------+-------------------+------------------+
1 row in set

说明:
定时任务配置有两种方式
第一种:MethodInvokingJobDetailFactoryBean
<bean id="myJobDetail"	class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject" ref="myJob" />
		<property name="targetMethod" value="work" />
		<!-- <property name="concurrent" value="false" /> -->
</bean>

如果用这种方式的话,要屏蔽一下配置
<property name="dataSource" ref="dataSource" />
		<property name="quartzProperties">
			<props>
				<prop key="org.quartz.scheduler.instanceName">defaultScheduler</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">20</prop>
				<prop key="org.quartz.threadPool.threadPriority">5</prop>
				<!-- JobStore配置 -->
				<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
				<!-- 集群配置 -->
				<prop key="org.quartz.jobStore.isClustered">true</prop>
				<prop key="org.quartz.jobStore.clusterCheckinInterval">15000</prop>
				<prop key="org.quartz.jobStore.maxMisfiresToHandleAtATime">1</prop>
				<prop key="org.quartz.jobStore.misfireThreshold">120000</prop>
				<!-- 表名配置 -->
				<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
			</props>
		</property>

第二种:JobDetailFactoryBean
<bean id="myQuartzJobDetail"
		class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass" value="job.MyQuartzJob" />
		<property name="name" value="myQuartzJob" />
		<!-- 任务完成之后是否依然保留到数据库,默认false -->
		<property name="durability" value="true" />
</bean>

主要是JobDetailFactory得实现不同,第一种不需要实现org.quartz.Job,而第二种需要实现org.quartz.Job;为什么会有这两种方式呢,用的时候该用那种方式,第一种方式定时任务存在RAM中,应用启动时,任务信息及任务调度信息易丢失,要避免任务信息及任务调度信息,需将任务相关信息持久化到RDB,这就是第二种方式的job为什么要实现org.quartz.Job原因,因为保存到数据库需要job-bean的相关信息。
了解更多关于任务持久化到RDB,请参考:
Quartz 任务存储JobStoreTX 持久化之RDB-源码分析: http://donald-draper.iteye.com/admin/blogs/2323409

猜你喜欢

转载自donald-draper.iteye.com/blog/2323591