- 浏览: 218628 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
Wangwei86609:
非常好的规则引擎框架,支持决策树和多线程运行规则https:/ ...
规则引擎 -
hzxlb910:
真详细,收藏哈
maven setting.xml配置说明 -
东方胜:
[b][/b]
脚本语言 Tcl -
345161974:
hyw520110 写道345161974 写道这个Visua ...
Visual Tcl Binary 完整版(完美中文支持) -
hyw520110:
345161974 写道这个Visual Tcl Binary ...
Visual Tcl Binary 完整版(完美中文支持)
在《Quartz 任务监控管理 (1)》http://www.iteye.com/topic/441951?page=1中,我们知道实现的因难是Job持久化需要序列化,主要是以处下三个问题:
一、org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean报 java.io.NotSerializableException异常,需要自己实现QuartzJobBean。
二、dao必须要实现序列化接口,Hibernate dao不能直接继承自HibernateDaoSupport,因为HibernateDaoSupport没有实现序列化接口,只能通过SessionFactory构造HibernateTemplate。
三、当库里己存在Trigger,应用启动时会从库里加载己存在Trigger,会报java.io.InvalidObjectException: Could not find a SessionFactory named: null等SessionFactory等相关异常。因为应用每次启动的得到的SessionFactory实例是不一样的,当从库里取到的Job进行反序列化时,Job里包含的SessionFactory与当前的SessionFactory不一致,所以为null。当时解决这问题采用了一个比较笨的方法,在SchedulerServiceImpl增加一个初始化方法
- @PostConstruct
- public void init() throws SchedulerException{
- logger.info("init start....................");
- scheduler.addJob(jobDetail, true);
- logger.info("init end.......................");
- }
@PostConstruct public void init() throws SchedulerException{ logger.info("init start...................."); scheduler.addJob(jobDetail, true); logger.info("init end......................."); }
并且增加
<property name="startupDelay" value="60"/>
让QuartzScheduler延时启动,为了保证init()先执行,init()是更新Job,其实只是为了更新当前的SessionFactory到Job中,保持Job里的SessionFactory与当前SessionFactory一致。我后来发现解决这个问题还有一个更好的方法,在org.springframework.scheduling.quartz.SchedulerFactoryBean是可配置的
- <property name="overwriteExistingJobs" value="true"/>
- <property name="jobDetails" >
- <list>
- <ref bean="jobDetail"/>
- </list>
- </property>
<property name="overwriteExistingJobs" value="true"/> <property name="jobDetails" > <list> <ref bean="jobDetail"/> </list> </property>
这样就可以达到与init一样的效果。
这三个问题,经过研究探索,现在都己经不是问题了。下面我简单说说这个三个问题的解决办法。
第一个问题:org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean报NotSerializableException异常,这个 spring bug 己经在http://jira.springframework.org/browse/SPR-3797找到解决方案,上面有牛人修改过的MethodInvokingJobDetailFactoryBean.java,详细源码请可以参考附件。哇塞,又可以POJO了。
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
- <beans>
- <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="dataSource" ref="dataSource"/>
- <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
- <property name="configLocation" value="classpath:quartz.properties"/>
- <!--这个是必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动-->
- <property name="startupDelay" value="30"/>
- <!--这个是可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了-->
- <property name="overwriteExistingJobs" value="true"/>
- <property name="jobDetails" >
- <list>
- <ref bean="jobDetail"/>
- </list>
- </property>
- </bean>
- <bean id="jobDetail" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
- <!--shouldRecover属性为true,则当Quartz服务被中止后,再次启动任务时会尝试恢复执行之前未完成的所有任务-->
- <property name="shouldRecover" value="true"/>
- <property name="targetObject" ref="customerService"/>
- <property name="targetMethod" value="testMethod1"/>
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/> <property name="configLocation" value="classpath:quartz.properties"/> <!--这个是必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动--> <property name="startupDelay" value="30"/> <!--这个是可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了--> <property name="overwriteExistingJobs" value="true"/> <property name="jobDetails" > <list> <ref bean="jobDetail"/> </list> </property> </bean> <bean id="jobDetail" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!--shouldRecover属性为true,则当Quartz服务被中止后,再次启动任务时会尝试恢复执行之前未完成的所有任务--> <property name="shouldRecover" value="true"/> <property name="targetObject" ref="customerService"/> <property name="targetMethod" value="testMethod1"/> </bean> </beans>
注意 <bean id="jobDetail" class="frameworkx.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">是修改过的MethodInvokingJobDetailFactoryBean。
第三个问题:从SchedulerServiceImpl 中去掉不需要的init() 方法,不用在SchedulerServiceImpl初始化后更新jobDeail。
- @PostConstruct
- public void init() throws SchedulerException{
- logger.info("init start....................");
- scheduler.addJob(jobDetail, true);
- logger.info("init end.......................");
- }
@PostConstruct public void init() throws SchedulerException{ logger.info("init start...................."); scheduler.addJob(jobDetail, true); logger.info("init end......................."); }
第二个问题与第三个是互相关联的,我想到要解决这两个问题的一个方案是Job中不要包含SessionFactory就没一切OK了, 因为SessionFactory是hibernate dao的属性,而hibernate dao是SimpleService的属性,因此SimpleService不能有任何hibernate dao属性了。如此SimpleService业务方法里需要的hibernate dao又如何获取呢?对 spring 的了解,我们知道可以通过ApplicationContext获取到任何spring bean,但是在这里ApplicationContext又怎么获取呢? ... 查看org.springframework.web.context.ContextLoaderListener找到org.springframework.web.context.ContextLoader.getCurrentWebApplicationContext()可以获取到ApplicationContext,增加一个SpringBeanService类,实现序列化接口,通过SpringBeanService可以获取到web己经加载的spring bean
- package com.sundoctor.example.service;
- import java.io.Serializable;
- import org.springframework.context.ApplicationContext;
- import org.springframework.stereotype.Service;
- import org.springframework.web.context.ContextLoader;
- @SuppressWarnings("unchecked")
- @Service("springBeanService")
- public class SpringBeanService implements Serializable{
- private static final long serialVersionUID = -2228376078979553838L;
- public <T> T getBean(Class<T> clazz,String beanName){
- ApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
- return (T)context.getBean(beanName);
- }
- }
package com.sundoctor.example.service; import java.io.Serializable; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.springframework.web.context.ContextLoader; @SuppressWarnings("unchecked") @Service("springBeanService") public class SpringBeanService implements Serializable{ private static final long serialVersionUID = -2228376078979553838L; public <T> T getBean(Class<T> clazz,String beanName){ ApplicationContext context = ContextLoader.getCurrentWebApplicationContext(); return (T)context.getBean(beanName); } }
因为Hibernate Dao不再持久到Job中,所在不再需要实现序列化接口,可以继承HibernateDaoSupport,当然也可以不继承,可以根据自己喜好的方式编写,不再有任何限制
- package com.sundoctor.example.dao;
- import org.hibernate.Session;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.orm.hibernate3.HibernateCallback;
- import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
- import org.springframework.stereotype.Repository;
- import com.sundoctor.example.model.Customer;
- import com.sundoctor.example.service.CustomerService;
- @Repository("customerDao")
- public class CustomerHibernateDao extends HibernateDaoSupport {
- private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);
- public Customer getCustomer2() {
- return (Customer) this.getHibernateTemplate().execute(new HibernateCallback() {
- public Object doInHibernate(Session session) {
- Customer customer = (Customer) session.createQuery("from Customer where id = 1").uniqueResult();
- logger.info("Customer2={}", customer);
- return customer;
- }
- });
- }
- public Customer getCustomer1() {
- Customer customer = (Customer) this.getHibernateTemplate().get(Customer.class, 1);
- logger.info("Customer1={}", customer);
- return customer;
- }
- }
package com.sundoctor.example.dao; import org.hibernate.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.stereotype.Repository; import com.sundoctor.example.model.Customer; import com.sundoctor.example.service.CustomerService; @Repository("customerDao") public class CustomerHibernateDao extends HibernateDaoSupport { private static final Logger logger = LoggerFactory.getLogger(CustomerService.class); public Customer getCustomer2() { return (Customer) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) { Customer customer = (Customer) session.createQuery("from Customer where id = 1").uniqueResult(); logger.info("Customer2={}", customer); return customer; } }); } public Customer getCustomer1() { Customer customer = (Customer) this.getHibernateTemplate().get(Customer.class, 1); logger.info("Customer1={}", customer); return customer; } }
因为hibernate dao 不再实现序列化接口和继承自HibernateDaoSupport,不能再注入到业务类中了。在业务类中注入以上的SpringBeanService,业务方法需要的hibernate dao通过以上的SpringBeanService.getBean获取
- package com.sundoctor.example.service;
- import java.io.Serializable;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.stereotype.Service;
- import com.sundoctor.example.dao.CustomerHibernateDao;
- import com.sundoctor.example.model.Customer;
- @Service("customerService")
- public class CustomerService implements Serializable {
- private static final long serialVersionUID = -6857596724821490041L;
- private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);
- private SpringBeanService springBeanService;
- @Autowired
- public void setSpringBeanService(@Qualifier("springBeanService") SpringBeanService springBeanService) {
- this.springBeanService = springBeanService;
- }
- public void testMethod1() {
- // 这里执行定时调度业务
- CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao");
- Customer customer = customerDao.getCustomer1();
- logger.info("AAAA:{}", customer);
- }
- public void testMethod2() {
- // 这里执行定时调度业务
- CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao");
- Customer customer = customerDao.getCustomer2();
- logger.info("BBBB:{}", customer);
- }
package com.sundoctor.example.service; import java.io.Serializable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import com.sundoctor.example.dao.CustomerHibernateDao; import com.sundoctor.example.model.Customer; @Service("customerService") public class CustomerService implements Serializable { private static final long serialVersionUID = -6857596724821490041L; private static final Logger logger = LoggerFactory.getLogger(CustomerService.class); private SpringBeanService springBeanService; @Autowired public void setSpringBeanService(@Qualifier("springBeanService") SpringBeanService springBeanService) { this.springBeanService = springBeanService; } public void testMethod1() { // 这里执行定时调度业务 CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao"); Customer customer = customerDao.getCustomer1(); logger.info("AAAA:{}", customer); } public void testMethod2() { // 这里执行定时调度业务 CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao"); Customer customer = customerDao.getCustomer2(); logger.info("BBBB:{}", customer); }
以上代码中hibernate dao 获取方法:
- CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao")获取方法;
CustomerHibernateDao customerDao =springBeanService.getBean(CustomerHibernateDao.class,"customerDao")获取方法;
三个主要问题就这样解决了。
附件中的其它源码介绍可以参考《Quartz 在 Spring 中如何动态配置时间》http://www.iteye.com/topic/399980?page=1和《Quartz任务监控管理 (1)》http://www.iteye.com/topic/441951?page=1。
发表评论
-
pushlet
2012-05-31 14:56 1168基于pushlet的文件监控系统的研究与实现 http ... -
@Transactional spring 配置事务
2012-04-25 11:15 2090@Transactional spring 配置事 ... -
Spring的组件自动扫描机制
2012-04-09 17:47 0Spring将所有的bean都纳入到IOC中创建、管理和维护。 ... -
struts&rest
2012-04-03 00:11 793深入浅出REST http://www.infoq. ... -
文件转码
2011-11-16 09:55 1991工程项目太多,各工程或各文件编码不统一时,可运行本工具类,把工 ... -
安装和使用SpringIDE-------III
2011-07-29 10:40 8372. 编写类文件 · ... -
安装和使用SpringIDE-------II
2011-07-29 10:39 681显示图表,如图: 发表于 @ 2006 ... -
安装和使用SpringIDE
2011-07-29 10:36 1127这篇文章谈谈如何安装与使用SpringIDE。作为辅助Sp ... -
使用AJDT简化AspectJ开发
2011-07-29 10:05 1019面向方面编程(AOP)可用来解决当今的 许多 应用需求 ... -
利用Apache的CLI来处理命令行
2011-05-16 17:02 977CLI是Jakarta Commons中的一个子类。如果你仅仅 ... -
CGlib简单介绍
2011-04-28 08:37 832CGlib概述:cglib(Code Generation L ... -
Java ClassLoader
2011-04-25 18:24 1001当Java编译器编译好.class ... -
Template模式与Strategy模式
2011-04-20 16:23 660template method模式和stra ... -
Ibatis读写CLOB数据
2011-03-21 14:21 1027转载:http://www.iteye.com/topic/7 ... -
轻松构建和运行多线程的单元测试
2011-03-18 22:09 972背景 并行程序 并行程序是指控制计算机系统中两个或多个分别 ... -
Cairngorm3中文简介
2011-03-18 22:07 1015官方原文地址:http://opensource.adobe. ... -
ibator改造之返回数据库注释和数据库分页
2010-12-23 17:24 2227转载:http://www.iteye.com ... -
Quartz任务监控管理 (1)
2010-10-28 23:27 1284转载:http://sundoctor.iteye.com/b ... -
Quartz 在 Spring 中如何动态配置时间
2010-10-28 23:25 1682转载: http://sundoctor.iteye.com ... -
使用org.apache.commons.net.ftp包开发FTP客户端,实现进度汇报,实现断点续传,中文支持
2010-10-28 21:09 1021使用org.apache.commons.net.ftp包开发 ...
相关推荐
2. **从数据库中获取定时任务**:Quartz允许将任务和触发器的信息存储在数据库中,这可以通过实现`SchedulerFactoryBean`的`overwriteExistingJobs`属性为`false`来实现。这样,当Quartz启动时,它会从数据库中读取...
2、定时任务(xxl-job)(XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。) 3、SpringCloudSchedule定时任务(使用...
spring-boot 2.0.2 数据库配置定时任务。spring-boot 2.0.2.RELEASE,将定时任务配置在数据库,启动项目的时候,用mybatis读取数据库,实例化对象,并设定定时任务。如果需要新增,减少,修改定时任务,仅需要修改...
DirectShow被广泛用于开发多媒体应用程序,它提供了丰富的API接口,可以处理视频捕获、播放、编辑等多种任务。在VB6中调用Quartz.dll,可以利用其强大的视频处理能力,为应用程序添加高级的视频播放特性。 该示例...
### Quart-Z 两次执行问题详解 #### 一、问题背景及概述 ...此外,还可以利用Spring Profiles来更好地管理不同环境下的配置差异。通过采取这些措施,可以有效地避免定时任务的重复执行问题,确保系统的稳定性和效率。
postgres quatrz初始化sql脚本文件、pg、quartz、qrtz_开头的表 配置文件需求修改 #org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore....
利用VB开放自定义播放器,基于系统Quatrz.dll的接口将媒体显示到指定的控件容器中,比如PictureBox,实现播放的基本功能,播放,暂停,停止,音量,平衡,进度,媒体的总时间和进度时间……感兴趣的VB发烧友可以下载...