spring 和quartz整合.docx
文本预览下载声明
Spring+Quartz的集群配置
2011年08月30日 ? HYPERLINK /category/programmer/java \o 查看 JAVA 中的全部文章 JAVA ? HYPERLINK /programmer/java/08-91.html \l respond \o 《Spring+Quartz的集群配置》上的评论 暂无评论
应用场景: 集群环境. 在多台服务器布置了相同的程序,程序中都包含有相同的定时器任务.如果不做处理,则会出现定时任务重复执行的问题,一般的业务场景这个是必须要避免的.
解决办法: 一. 只在一台服务器发布带有定时器的程序,其他的全都去除定时任务再发布. ? (如果这台服务器宕掉了,那就悲剧了) ; 二. 采用Quratz开源定时任务框架,并配置集群.(好处在于spring集成了对Quratz的支持,如果你也用了spring+Quratz,往下看).
本用例采用框架版本: Spring 3.0 + Quratz 1.8.5 ? ?参考: HYPERLINK /blog/337886 \t _blank /blog/337886
起初采用spring对Quratz的原生支持,但是报错. 异常信息:
java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property methodInvoker is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
据说是spring的bug,按照以上地址里给的解决办法,重写了MethodInvokingJobDetailFactoryBean. 但诡异的是,仍然报出 java.io.NotSerializableException,由于我的定时器里引用了Service层,这里抛出的是dataSource is not serializable.本以为是因为序列化的时候把Dao属性也获取并序列化了,所以就把getDao()都去掉了,但是还是会报错,看来不是按照这个逻辑执行程序的,按照上面地址里说的方案之一,说可以把service和Dao层都继承Serializable,但是我放弃了,因为我没办法把dataSource也继承 Serializable. 之后看了下面的留言,有一位仁兄写好了demo,并分享了出来.地址:/source/2777549 ? OK,下面说详细代码.因为我下了那个demo之后还弄了好一会儿,有必要记录一下.
解决思路: 编写一个带有String类型属性的,实现Serializable的伪任务类,执行任务调度时,调用此类的实例,并注入真正要调用的类的Bean ID.也就是说,初始化任务的时候,注入的是这个类,而类中调用真正要执行的任务.从而避免了序列化问题.
伪任务类PseudoJob.java
/pre
public class BootstrapJob implements Serializable{
private static final long serialVersionUID = 4195235887559214105L;
private String targetJob ;
public void execute(ApplicationContext cxt) {
Job job = (Job)cxt.getBean(this.targetJob);
job.execute() ;
}
public String getTargetJob() {
return targetJob;
}
public void setTargetJob(String targetJob) {
this.targetJob = targetJob;
}
}
Job接口类:定时任务类必须继承Job接口
public interface Job extends Serializable{
void execute();
}
MethodInvokingJobDetailFactoryBean
import mons.logging.Log;
import mons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.q
显示全部