quartz.properties"/>
— 就是下面这句,因为该 bean 只能使用类反射来重构
quartz.properties 文件的内容:
org.quartz.scheduler.instanceName=mapScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate
org.quartz.jobStore.dataSource=myXADS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.dataSource.myXADS.jndiURL=jdbc/TestQuartzDS
org.quartz.dataSource.myXADS.jndiAlwaysLookup=DB_JNDI_ALWAYS_LOOKUP
org.quartz.dataSource.myXADS.java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
org.quartz.dataSource.myXADS.java.naming.provider.url=t3:
//localhost:
7020
org.quartz.dataSource.myXADS.java.naming.security.principal=weblogic
org.quartz.dataSource.myXADS.java.naming.security.credentials=weblogic
3. 重写 quartz 的 QuartzJobBean 类
原因是在使用 quartz+spring 把 quartz 的 task 实例化进入数据库时,会产生:
serializable 的错误,原因在于:
execute
这个 MethodInvokingJobDetailFactoryBean 类中的 methodInvoking 方法,是不支持序列化的,因此在把QUARTZ 的 TASK 序列化进入数据库时就会抛错。
网上有说把 SPRING 源码拿来,修改一下这个方案,然后再打包成 SPRING.jar 发布,这些都是不好的方法,是不安全的。
必须根据 QuartzJobBean 来重写一个自己的类,然后使用 SPRING 把这个重写的类(我们就名命它为:
MyDetailQuartzJobBean )注入 appContext 中后,再使用 AOP 技术反射出原有的 quartzJobx( 就是开发人员原来已经做好的用于执行 QUARTZ 的 JOB 的执行类 ) 。
下面来看 MyDetailQuartzJobBean 类:
publicclassMyDetailQuartzJobBeanextendsQuartzJobBean{
protectedfinalLoglogger=LogFactory.getLog(getClass());
privateStringtargetObject;
privateStringtargetMethod;
privateApplicationContextctx;
protectedvoidexecuteInternal(JobExecutionContextcontext)
throwsJobExecutionException{
try{
logger.info("execute["+targetObject+"]atonce>>>>>>");
ObjectotargetObject=ctx.getBean(targetObject);
Methodm=null;
try{
m=otargetObject.getClass().getMethod(targetMethod,
newClass[]{});
m.invoke(otargetObject,newObject[]{});
}catch(SecurityExceptione){
logger.error(e);
}catch(NoSuchMethodExceptione){
logger.error(e);
}
}catch(Exceptione){
thrownewJobExecutionException(e);
}
}
publicvoidsetApplicationContext(ApplicationContextapplicationContext){
this.ctx=applicationContext;
}
publicvoidsetTargetObject(StringtargetObject){
this.targetObject=targetObject;
}
publicvoidsetTargetMethod(StringtargetMethod){
this.targetMethod=targetMethod;
}
}
再来看完整的 quartz.xml (注意红色加粗部分尤为重要):
xmlversion="1.0"encoding="UTF-8"?
>
DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:
//www.springframework.org/dtd/spring-beans.dtd ">
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
quartz.properties"/>
com.testcompany.framework.quartz. MyDetailQuartzJobBean
0/5****?
4. 下载最新的 quartz1.8 版,把 quartz-all-1.8.4.jar,quartz-oracle-1.8.4.jar,quartz-weblogic-1.8.4.jar 这三个包放到 web-inf/lib 目录下,布署。
测试:
几个节点都带有 quartz 任务,此时只有一台 quartz 在运行,另几个节点上的 quartz 没有运行。
此时手动 shutdown 那台运行 QUARTZ (在程序里加 system.out.println(“executeonce…”), 运行 quartz的那个节点在后台会打印 executeonce )的节点,过了 7 秒左右,另一个节点的 quartz 自动监测到了集群中运行着的 quartz 的 instance 已经 shutdown ,因此 quartz 集群会自动把任一台可用的 APP 上启动起一个 quartzjob 的任务。
自此, QUARTZ 使用 HA 策略的集群大功告成,不用改原有代码,配置一下我们就可作到 QUARTZ 的集群与自动错误冗余。