Spring Quartz 持久化解决方案
Quartz是实现了序列化接口的,包括接口,所以可以使用标准方式序列化到数据库。
而Spring2.5.6在集成Quartz时却未能考虑持久化问题。
Spring对JobDetail进行了封装,却未实现序列化接口,所以持久化的时候会产生NotSerializable问题,这也是网上一直在那边叫嚣为什么不能持久化到数据库问题,哥今天看了下Spring源码,发现Spring对Quartz持久化的问题.
1. 不知道Spring未来会不会对持久化的支持,不过我们可以有如下解决方案,比如改写
Spring的代码,实现序列化接口.
2. 不使用Spring的Fatory,自己实现任务的初始化.
既然Spring不支持持久化,那么持久化任务还是自己编写实现吧,否则每次都需要打包发布,麻烦,自己编写的类与Quartz完全兼容.
注意:为什么Spring不支持外配置任务,可能也是考虑到这方面问题所以才不提供这些任务的执行化支持.[配置文件配置与数据库配置重复]
直接使用Quartz是支持序列化功能,比如直接使用页面配置Quartz界面,设置任务执行时间等属性。
通过配置实现的是不应该初始化到数据库,否则直接在数据库中配置了。不过也是可以配置的,通过改写JobDetailBean.代码如下:
- package org.frame.auth.service;
- import java.util.Map;
- import org.quartz.Job;
- import org.quartz.JobDetail;
- import org.quartz.Scheduler;
- import org.springframework.beans.factory.BeanNameAware;
- import org.springframework.beans.factory.InitializingBean;
- import org.springframework.scheduling.quartz.DelegatingJob;
- import org.springframework.scheduling.quartz.SchedulerFactoryBean;
- public class PersistentJobDetailBean extends JobDetail
- implements BeanNameAware, InitializingBean {
- private static final long serialVersionUID = -4389885435844732405L;
- private Class actualJobClass;
- private String beanName;
- /**
- * Overridden to support any job class, to allow a custom JobFactory
- * to adapt the given job class to the Quartz Job interface.
- * @see SchedulerFactoryBean#setJobFactory
- */
- public void setJobClass(Class jobClass) {
- if (jobClass != null && !Job.class.isAssignableFrom(jobClass)) {
- super.setJobClass(DelegatingJob.class);
- this.actualJobClass = jobClass;
- }
- else {
- super.setJobClass(jobClass);
- }
- }
- /**
- * Overridden to support any job class, to allow a custom JobFactory
- * to adapt the given job class to the Quartz Job interface.
- */
- public Class getJobClass() {
- return (this.actualJobClass != null ? this.actualJobClass : super.getJobClass());
- }
- /**
- * Register objects in the JobDataMap via a given Map.
- * <p>These objects will be available to this Job only,
- * in contrast to objects in the SchedulerContext.
- * <p>Note: When using persistent Jobs whose JobDetail will be kept in the
- * database, do not put Spring-managed beans or an ApplicationContext
- * reference into the JobDataMap but rather into the SchedulerContext.
- * @param jobDataAsMap Map with String keys and any objects as values
- * (for example Spring-managed beans)
- * @see SchedulerFactoryBean#setSchedulerContextAsMap
- */
- public void setJobDataAsMap(Map jobDataAsMap) {
- getJobDataMap().putAll(jobDataAsMap);
- }
- /**
- * Set a list of JobListener names for this job, referring to
- * non-global JobListeners registered with the Scheduler.
- * <p>A JobListener name always refers to the name returned
- * by the JobListener implementation.
- * @see SchedulerFactoryBean#setJobListeners
- * @see org.quartz.JobListener#getName
- */
- public void setJobListenerNames(String[] names) {
- for (int i = 0; i < names.length; i++) {
- addJobListener(names[i]);
- }
- }
- public void setBeanName(String beanName) {
- this.beanName = beanName;
- }
- public void afterPropertiesSet() {
- if (getName() == null) {
- setName(this.beanName);
- }
- if (getGroup() == null) {
- setGroup(Scheduler.DEFAULT_GROUP);
- }
- }
- }
这里把Spring的ApplicationContext去掉了,因为这个属性没有实现序列化接口。其他配置与原告一致:
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" " http://www.springframework.org/dtd/spring-beans.dtd ">
- <beans default-autowire="byName">
- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- <property name="url" >
- <value><![CDATA[jdbc:mysql://localhost:3306/txl?connectTimeout=1000&useUnicode=true&characterEncoding=utf-8]]></value>
- </property>
- <property name="username" value="root"/>
- <property name="password" value=""/>
- </bean>
- <bean id="jobDetail" class = "org.frame.auth.service.PersistentJobDetailBean">
- <property name="jobClass" value="org.frame.auth.service.PersistentJob"></property>
- </bean>
- <!-- <bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean" >-->
- <!-- <property name="jobDetail" ref="jobDetail"></property>-->
- <!-- <property name="startDelay" value="1000"></property>-->
- <!-- <property name="repeatInterval" value="3000"></property>-->
- <!-- <property name="jobDataAsMap">-->
- <!-- <map>-->
- <!-- <entry key="message" value="this is trigger"></entry>-->
- <!-- </map>-->
- <!-- </property>-->
- <!-- </bean>-->
- <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >
- <property name="jobDetail" ref="jobDetail"/>
- <property name="cronExpression">
- <value>0/10 * * * * ?</value>
- </property>
- </bean>
- <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
- <property name="dataSource" ref="dataSource"></property>
- <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
- <property name="configLocation" value="classpath:quartz.properties"/>
- </bean>
- </beans>
org.frame.auth.service.PersistentJob这个类很简单,如下:
- package org.frame.auth.service;
- import org.quartz.Job;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- public class PersistentJob implements Job {
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- System.out.println("spring quartz!");
- }
- }
有人可能会说,你这种任务调度持久化就没有意义了,是的,一般持久化到数据库的代码如下:
- package org.frame.auth.service;
- import java.util.Map;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.quartz.StatefulJob;
- public class PersistentJob implements StatefulJob {
- @Override
- public void execute(JobExecutionContext context) throws JobExecutionException {
- // TODO Auto-generated method stub
- Map map = context.getJobDetail().getJobDataMap();
- System.out.println("["+context.getJobDetail().getName()+"]"+map.get("message"));
- map.put("message", "updated Message");
- }
- }
这样的话,信息message就会持久化到数据库中了.可以建立系统的连锁调度,这根据你的业务需求了.
在Spring中配置的任务通过我这种修改是可以运行,不过每次运行都需要把原先的任务删除,否则会提示任务已经存在,Quartz的优势是就算服务器停止,下次重启能够恢复原先的任务并继续执行.
Spring Quartz 持久化解决方案的更多相关文章
- 基于spring+quartz的分布式定时任务框架
问题背景 我公司是一个快速发展的创业公司,目前有200人,主要业务是旅游和酒店相关的,应用迭代更新周期比较快,因此,开发人员花费了更多的时间去更=跟上迭代的步伐,而缺乏了对整个系统的把控 没有集群之前 ...
- Spring+Quartz 集群
这几天给Spring+Quartz的集群折腾得死去活来,google了无数页总算搞定,记下一些要点备以后使用. 单独的Quartz集群在http://unmi.blogjava.net/有Unmi翻译 ...
- Spring+quartz 实现定时任务job集群配置
为什么要有集群定时任务? 因为如果多server都触发相同任务,又同时执行,那在99%的场景都是不适合的.比如银行每晚24:00都要汇总营业额.像下面3台server同时进行汇总,最终计算结果可能是真 ...
- Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群
Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群 >>>>>>>>>>>>>> ...
- Spring+quartz 实现定时任务job集群配置【原】
为什么要有集群定时任务? 因为如果多server都触发相同任务,又同时执行,那在99%的场景都是不适合的.比如银行每晚24:00都要汇总营业额.像下面3台server同时进行汇总,最终计算结果可能是真 ...
- 【示例】Spring Quartz入门
JAVA 针对定时任务,有 Timer,Scheduler, Quartz 等几种实现方式,其中最常用的应该就是 Quartz 了. 一. Quartz的基本概念 在开始之前,我们必须了解以下的几个基 ...
- Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入
Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入 Spring4整合quartz2.2.3中Job任务使用@Autowired不能注入 >> ...
- Spring+quartz集群解决多服务器部署定时器重复执行的问题
一.问题描述 Spring自带的Task虽然能很好使用定时任务,只需要做些简单的配置就可以了.不过如果部署在多台服务器上的时候,这样定时任务会在每台服务器都会执行,造成重复执行. 二.解决方案 Spr ...
- spring + quartz 分布式自定义注解
相关技术 本文采用spring + quartz的方案.使用mysql作为任务的持久化,支持分布式. 自定义注解 1.启用定时任务 @Target(ElementType.TYPE) @Retenti ...
随机推荐
- CF2B The least round way 题解
都是泪呀...↑ 题目传送门 题意(直接复制了QWQ) 题目描述 给定由非负整数组成的\(n \times n\)的正方形矩阵,你需要寻找一条路径: 以左上角为起点, 每次只能向右或向下走, 以右下角 ...
- Elasticsearch介绍及安装部署
本节内容: Elasticsearch介绍 Elasticsearch集群安装部署 Elasticsearch优化 安装插件:中文分词器ik 一.Elasticsearch介绍 Elasticsear ...
- spring-boot分环境打包为tar包
1.pom配置 <!-- 多环境打包 start --> <profiles> <!-- 开发环境配置 --> <profile> <id> ...
- event对象在IE和firefox下兼容写法
由于项目需求要求只能允许用户输入数字和小数,用到了event.keycode后IE系列.chrome浏览器都无问题,在firefox下出现了event not defined的错误 原因:火狐下eve ...
- jenkins定时构建
打开job的配置界面,在构建触发器栏下有Poll SCM(定时检查源码变更并构建)和Build periodically(周期进行项目构建,不关心源码是否变更) 定时构建语法: * * * * *(和 ...
- 【基础知识】.Net基础加强第01天
1.#region *** 可以将一个代码块折叠起来 #endregion 2.Visiual stdio 快捷方式 Ctrl + K + C //注释代码 Ctrl + K + U //取消代码注释 ...
- Python 实现扫码二维码登录
最近在做一个扫码登录功能,为此我还在网上搜了一下关于微信的扫描登录的实现方式.当这个功能完成了后,我决定将整个实现思路整理出来,方便自己以后查看也方便其他有类似需求的程序猿些. 要实现扫码登录我们需要 ...
- virtualenv虚拟环境安装不同版本的django
在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4.所有第三方的包都会被pip安装到Python3的site-packages目录下. 如果我们要同时开发多个应用程序,那这 ...
- 【拉格朗日插值法】【找规律】【高精度】Gym - 101156G - Non-Attacking Queens
题意:问你n*n的国际象棋棋盘上放3个互不攻击皇后的方案数. oeis……公式见代码内 //a(n) = 5a(n - 1) - 8a(n - 2) + 14a(n - 4) - 14a(n - 5) ...
- hdu 5248 贪心
题意: