Quartz2.2.1开发问题

一、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

四、一旦QuartzJobBean类或里面的属性被修改,那么数据库中对应的qrtz_job_details保存的job_class_name还是以前的QuartzJobBean,这导致这个旧的job再一次重新执行时,会找不到相应的QuartzJobBean,而报空指针异常。


第二个问题与第三个是互相关联的,我想到要解决这两个问题的一个方案是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);
 }
}

因为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;
 }
}

因为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);
 }

customerService是我们的Job具体执行的类,它必须实现序列化,因为它会被序列化到表qrtz_job_details中的job_class_name字段中,所以springBeanService属性也必须序列化,这里其实也可以不用写springbeanservice,而是直接在testMethod中使用applicationContext.getBean去拿到dao,然后进行业务操作。

如果当任务执行的时间点上,正好服务器down掉或由于其他原因任务没有顺利完成
该如何自动或手动唤醒它,让他顺利执行呢?

//获取到Scheduler
Scheduler scheduler = ...;//(Scheduler)springContext.getBean("quartzScheduler");
//通过trigger name和trigger group得到SimpleTrigger 
SimpleTrigger trigger = (SimpleTrigger)scheduler.getTrigger("52f071d3-eebb-4308-abeb-9ce8ec58aba4", "DEFAULT");
//重新设置Trigger己经触发的次数
int timesTriggered = trigger.getTimesTriggered();
trigger.setTimesTriggered(timesTriggered > 0 ? timesTriggered -1 : 0);
//可选,重新设置开始触发时间
//trigger.setStartTime(startTime);
//可选,重新设置下次触发时间
//trigger.setNextFireTime(nextFireTime);
//等等,还有许多可选配置可以重新设置
//调用rescheduleJob重新调度tirgger
scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);

 

转载于:https://my.oschina.net/javayan/blog/607042

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值