Quartz2.2.1開發問題

1、org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean報 java.io.NotSerializableException異常,須要本身實現QuartzJobBean。
2、dao必需要實現序列化接口,Hibernate dao不能直接繼承自HibernateDaoSupport,由於HibernateDaoSupport沒有實現序列化接口,只能經過SessionFactory構造HibernateTemplate。
3、當庫裏己存在Trigger,應用啓動時會從庫里加載己存在Trigger,會報java.io.InvalidObjectException: Could not find a SessionFactory named: null等SessionFactory等相關異常。由於應用每次啓動的獲得的SessionFactory實例是不同的,當從庫裏取到的Job進行反序列化時,Job裏包含的SessionFactory與當前的SessionFactory不一致,因此爲nulljava

4、一旦QuartzJobBean類或裏面的屬性被修改,那麼數據庫中對應的qrtz_job_details保存的job_class_name仍是之前的QuartzJobBean,這致使這個舊的job再一次從新執行時,會找不到相應的QuartzJobBean,而報空指針異常。web


第二個問題與第三個是互相關聯的,我想到要解決這兩個問題的一個方案是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 beanspring

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,而後進行業務操做。session

若是當任務執行的時間點上,正好服務器down掉或因爲其餘緣由任務沒有順利完成
該如何自動或手動喚醒它,讓他順利執行呢?app

//獲取到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);
相關文章
相關標籤/搜索