[size=medium]
java web开发当中常用到定时任务,说到定时任务相信你一定或多或少了解quartz。在单台应用服务器上配置spring + quartz没有什么问题,这样的文章网络上应该也有很多,但是当你把应用放到集群环境中则会出问题,每台服务器上的定时任务并不知道其他服务器上的定时 任务的存在,各自执行产生资源竞争,可能就会导致出现脏数据。

本篇文章讲解了如何在集群环境中配置定时任务,用到的是spring4 + quartz2.2.1,下面请跟我一步一步进行配置。

如果你使用maven,添加引入;否则可以官网下载最新包。[/size]

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

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




[size=medium] 1.新建定时任务执行java类TestJob,集成了QuartzJobBean并实现了executeInternal方法。[/size]


import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TestJob extends QuartzJobBean{

	@Override
	protected void executeInternal(JobExecutionContext context)
			throws JobExecutionException {
		System.out.pringln("定时任务执行成功");	
	}
}




2.新建quartz.xml配置文件,并在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.xsd">

	<!-- 
		定时任务,此处使用JobDetailFactoryBean而非MethodInvokingJobDetailFactoryBean,是因为MethodInvokingJobDetailFactoryBean存在序列化bug。
		如果你的项目中使用了MethodInvokingJobDetailFactoryBean,并且不想对此进行修改,可以草考该篇文章:http://mushme.iteye.com/blog/1874370
	-->
	<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass" value="你的项目包路径.TestJob" />
	</bean>

	<!--
		定义job执行逻辑,此处定义0 0 6,20 * * ?,表示每天上午6点,下午8点执行。具体配置方法请自行搜索cronExpression
	-->
	<bean id="jobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail" ref="jobDetail" />
		<property name="cronExpression" value="0 0 6,20 * * ?" />
	</bean>

	<!-- 总调度用于启动Spring定时器 -->
	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<!-- 
			虽然terracotta买下了quartz,quartz已经支持terracotta集群配置,但是此篇文章依旧使用数据库支持quartz集群的方式 
			项目已经配置了数据源,此处直接引用
		-->
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		<property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
		<!-- quartz配置文件 -->
		<property name="configLocation" value="classpath:quartz.properties" />
		<property name="triggers">
			<list>
				<ref bean="jobTrigger" />
			</list>
		</property>
	</bean>
</beans>



[size=medium]在spring配置文件中引入quartz.xml。



3.上面的配置文件中引入了quartz.properties,我们在src下新建此文件,并加入以下内容。[/size]


#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
#\u552F\u4E00\u6807\u8BC6\uFF0C\u540C\u4E00\u4E2A\u96C6\u7FA4\u7684\u540D\u79F0\u5FC5\u987B\u4E00\u81F4
org.quartz.scheduler.instanceName = MyClusteredScheduler
#auto\uFF0C\u5219quartz\u4F1A\u6839\u636E\u65F6\u95F4\u548C\u4E3B\u673A\u540D\u751F\u6210\uFF0C\u786E\u4FDD\u552F\u4E00
org.quartz.scheduler.instanceId = AUTO


#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

#jobstoretx\u5219\u4EFB\u52A1\u4F1A\u88AB\u6301\u4E45\u5316\u5230\u6570\u636E\u4E2D\uFF0C\u9ED8\u8BA4\u4E3ARAMJobStore\uFF0C\u9ED8\u8BA4\u4F1A\u88AB\u7EF4\u62A4\u5230\u5185\u5B58\u4E2D\uFF0C\u96C6\u7FA4\u7684\u65F6\u5019\u5FC5\u987B\u4FEE\u6539
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_

#ture\u5219\u6B64\u5B9E\u4F8B\u9700\u8981\u53C2\u52A0\u5230\u96C6\u7FA4\u4E2D
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000




[size=medium] 4.此篇文章讲的是基于数据库的quartz集群,还缺少quartz集群所需要的表,在最新的quartz包中可以找到建表sql,如果你闲麻烦,那就找找文本的附件吧。



当你创建了quartz集群锁需要的表,并且进行了以上配置,就可以启动项目验证quartz集群是否可以正常运行了。


PS:有不明白的地方欢迎留言,如果此篇文章对你有帮助请赞一下,欢迎分享。[/size]