详细步骤如下:
1、 按照Quartz集群工作原理
图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知
在数据库中建表。建表模版在Quartz包下docs/dbTables下,选择相应的数据库和版本即可。DB2_V8的11个Table列表如下:
备注:配置的定时器会在项目第一次起来的时候存储到数据库
QRTZ_JOB_LISTENERS
QRTZ_TRIGGER_LISTENERS
QRTZ_FIRED_TRIGGERS
QRTZ_PAUSED_TRIGGER_GRPS
QRTZ_SCHEDULER_STATE
QRTZ_LOCKS
QRTZ_SIMPLE_TRIGGERS
QRTZ_CRON_TRIGGERS
QRTZ_TRIGGERS
QRTZ_JOB_DETAILS
QRTZ_CALENDARS
QRTZ_BLOB_TRIGGERS
2、 配置数据库连接池,如果spring已经配置则不需要再另行配置,只需在后面配置的applicationContext-quartz.xml引入即可。
applicationContext.xml:
1
<bean id="propertyConfigurer"
2class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
3 <property name="location">
4 <value>classpath:dataConfig.properties</value>
5 </property>
6</bean>
7 <bean id="ds34" class="org.apache.commons.dbcp.BasicDataSource"
8 destroy-method="close">
9 <property name="driverClassName">
10 <value>${ds34.driver}</value>
11 </property>
12 <property name="url">
13 <value>${ds34.url}</value>
14 </property>
15 <property name="username">
16 <value>${ds34.username}</value>
17 </property>
18 <property name="password">
19 <value>${ds34.password}</value>
20 </property>
21 <property name="maxActive" value="5"></property>
22 <property name="maxIdle" value="20"></property>
23 <property name="maxWait" value="50"></property>
24 <property name="defaultAutoCommit" value="true"></property>
25</bean>
dataConfig.properties:
ds34.driver=com.ibm.db2.jcc.DB2Driver
ds34.url=jdbc:db2://192.168.*.*:50000/XXXX
ds34.username=admin
ds34.password=*******
3、 配置quartz.properties
org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。
org.quartz.scheduler.instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID。
org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。
org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。
org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。
quartz.properties:
1
##Quartz 调度任务所需的配置文件
2
3##org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。
4org.quartz.scheduler.instanceName = HumsScheduler
5##org.quartz.scheduler.instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID。
6org.quartz.scheduler.instanceId = AUTO
7
8orgorg.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
9org.quartz.threadPool.threadCount = 10
10org.quartz.threadPool.threadPriority = 5
11org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
12
13org.quartz.jobStore.misfireThreshold = 60000
14 ##org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。
15 ##因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。
16 ##这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。
17orgorg.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
18orgorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
19org.quartz.jobStore.tablePrefix = QRTZ_
20org.quartz.jobStore.maxMisfiresToHandleAtATime=10
21##org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。
22##这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。
23org.quartz.jobStore.isClustered = true
24##org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。
25##Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。
26##通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。
27org.quartz.jobStore.clusterCheckinInterval = 20000
4、 配置applicationContext-quartz.xml
备注:第一次配置生效,会存储到数据库里(配置生效后删除配置无效)
1
<?xml versinotallow="1.0" encoding="UTF-8"?>
2
3<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
4<beans>
5 <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
6 <property name="dataSource">
7 <ref bean="secruity_dataSource"/> <!--数据源引用指向,包含集群所需的所有表-->
8 </property>
9 <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
10<!--applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定义的key得到对应的spring上下文-->
11 <property name="configLocation" value="classpath:quartz.properties"/>
12<!--configLocation:用于指明quartz的配置文件的位置 -->
13 <property name="triggers">
14 <list>
15 <ref bean="trigger1"/>
16 </list>
17 </property>
18 </bean>
19<bean id="jobDetail1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
20 <property name="jobClass">
21 <value>继承QuartzJobBean的类的引用(com.rundatop.assist.biz.remind.controller.MethodInvokeJob)</value>
22 </property>
23</bean>
24 <bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
25 <property name="jobDetail" ref="jobDetail1"/>
26 <property name="cronExpression" value="0 0/5 * ? * * *"/>
27<!—cronExpression 表达式 -->
28 </bean>
29</beans>
5、 配置Job任务注意:加入定时任务有两种方式:
① 继承QuartzJobBean的类,重写executeInternal(),详细写法:
<
bean
id
="jobDetail1"
class
="org.springframework.scheduling.quartz.JobDetailBean"
>
<
property
name
="jobClass"
>
<
value
>
继承QuartzJobBean的类的引用(
com.rundatop.assist.biz.remind.controller.MethodInvokeJob
)
</
value
>
</
property
>
</
bean
>
② 用org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean指定类和方法,但是直接使用会报java.io.NotSerializableException异常,一般用网上流传的(需要将两个类copy到自己的工程下,要有springJAR包,Job需要持久化到数据库中,SimpleService必须实现Serializable)frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean,可以参考: http://jira.springframework.org/browse/SPR-3797。详细写法:
1
< bean
id
="jobDetail1"
class
=" 工程里MethodInvokingJobDetailFactoryBean的路径.MethodInvokingJobDetailFactoryBean"
>
2
<
property
name
="targetObject"
ref
="simpleService"
/>
3
<
property
name
="targetMethod"
value
="testMethod1"
/>
4
<
property
name
="shouldRecover"
value
="true"
/>
5
</ bean
>
6、 配置到spring配置文件,自动调度任务。
< context-param >
< param-name
>contextConfigLocation
</
param-name
>
< param-value
>
<!-- Quartz Spring applicationContext
-->
WEB-INF/classes/applicationContext-quartz.xml
</ param-value
>
</ context-param >
7、 继承类QuartzJobBean调用方法
说明:①使用注解的方式@service(“service名字”)例如@Service("remindService")
run())
③SerializableMethodInvoker配置
package com.rundatop.assist.biz.remind.controller;
import java.io.Serializable;
import org.springframework.util.MethodInvoker;
public class SerializableMethodInvoker extends MethodInvoker implements Serializable{
private static final long serialVersionUID = -8151325815754992667L;
}<strong>
</strong>
④ MethodInvokeJob配置(配置完成后即可使用)
package com.rundatop.assist.biz.remind.controller;
import java.lang.reflect.InvocationTargetException;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import com.rundatop.core.exception.BizRuntimeException;
import com.rundatop.core.spring.ApplicationContext;
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class MethodInvokeJob extends QuartzJobBean{
@Autowired
ApplicationContext applicationContext;
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
String arr[]=this.resolveBeanExpression(" remindService# run");
SerializableMethodInvoker invoker=new SerializableMethodInvoker();
invoker.setTargetObject(applicationContext.getBean(arr[0]));
invoker.setTargetMethod(arr[1]);
try {
invoker.prepare();
invoker.invoke();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String[] resolveBeanExpression(String execFunc) throws BizRuntimeException{
String[] arr=execFunc.split("#");
if(arr.length==1)
throw new BizRuntimeException("出错了!!");
return arr;
}
}