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);