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.代码如下:

  1. 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去掉了,因为这个属性没有实现序列化接口。其他配置与原告一致:

  1. <?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这个类很简单,如下:

  1. 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!");  }  }  



有人可能会说,你这种任务调度持久化就没有意义了,是的,一般持久化到数据库的代码如下:

  1. 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的优势是就算服务器停止,下次重启能够恢复原先的任务并继续执行.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/72074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

865. 具有所有最深节点的最小子树(javascript)865. Smallest Subtree with all the Deepest Nodes

给定一个根为 root 的二叉树&#xff0c;每个节点的深度是 该节点到根的最短距离 。 返回包含原始树中所有 最深节点 的 最小子树 。 如果一个节点在 整个树 的任意节点之间具有最大的深度&#xff0c;则该节点是 最深的 。 一个节点的 子树 是该节点加上它的所有后代的集合…

【计算机网络】 IP协议格式以及以太网帧结构

文章目录 IP协议格式以太网帧结构 IP协议格式 IP工作在网络层 IP头分为两部分&#xff0c;固定部分和可变部分&#xff0c;固定部分就是一定要带这些数据&#xff0c;正常存储应该是连续的&#xff0c;并不是像图中这样会换行&#xff0c;图中只是为了方便观察。 首先是一个版…

山洪、地质灾害监测利器-泥石流、山体滑坡AI视觉仪

1、设备介绍 AI视觉仪通过AI算法智能化摄像机&#xff0c;能够及时、全面的把握边坡潜在安全风险&#xff0c;有效防范自然灾害。支持全天候运行&#xff0c;在恶劣环境及气候条件下仍能正常进行监测数据采集。自动识别监控区域内是否有泥石流、山体滑坡等&#xff0c;一旦检测…

uni-app:重置表单数据

效果 代码 <template><form><input type"text" v-model"inputValue" placeholder"请输入信息"/><input type"text" v-model"inputValue1" placeholder"请输入信息"/><input type&quo…

排序之插入排序

文章目录 前言一、直接插入排序1、基本思想2、直接插入排序的代码实现3、直接插入排序总结 二、希尔排序1、希尔排序基本思想2、希尔排序的代码实现3、希尔排序时间复杂度 前言 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大…

Java基础(二十)Stream练习

Stream练习 1. 拼接 给定一个字符串数组,使用 Stream 把所有字符串拼接成一个字符串。 import java.util.Arrays; import java.util.stream.Collectors;public class StringJoinWork01 {public static void main(String[] args) {String[] arr {"a", "b&quo…

IDEA找不到Maven窗口

有时候导入项目或者创建项目时候Maven窗口找不到了 然后指定项目的pom.xml文件

torch.bmm功能解读

bmm 是 batched matrix multiple 的简写&#xff0c;即批量矩阵乘法&#xff0c;矩阵是二维的&#xff0c;加上batch一个维度&#xff0c;因此该函数的输入必须是两个三维的 tensor&#xff0c;三个维度代表的含义分别是&#xff1a;&#xff08;批量&#xff0c;行&#xff0c…

【python手写算法】逻辑回归实现分类(含公式推导)

公式推导&#xff1a; 代码实现&#xff1a; # codingutf-8 import matplotlib.pyplot as plt import numpy as npdef f(w1,x1,w2,x2,b):zw1*x1w2*x2breturn 1/(1np.exp(-z)) if __name__ __main__:X1 [12.46, 0.25, 5.22, 11.3, 6.81, 4.59, 0.66, 14.53, 15.49, 14.43,2.1…

DHCP的interface(接口),global(全局)配置以及DHCP relay(中继),DHCP snooping,DHCP option

目录 1.DHCP的接口&#xff08;interface&#xff09;配置 2.DHCP的全局&#xff08;global&#xff09;配置 3.dhcp relay 4.dhcp snooping 5.option 这里有一个简单的拓扑图 交换机配置命令如下 The device is running!<Huawei> <Huawei>sys Enter system …

Android 动画之插值器PathInterpolator

Android 的View动画、属性动画都可以设置动画插值器&#xff0c;以此来实现不同的动画效果。 这篇文章 Android View动画整理 有介绍各种插值器的效果&#xff0c;这一篇专访 PathInterpolator 。 参考官网 添加曲线动作 &#xff0c; PathInterpolator 基于 贝塞尔曲线 或 …

2023 大学生数学建模竞赛-C题-第一问

题目&#xff1a; 在生鲜商超中&#xff0c;一般蔬菜类商品的保鲜期都比较短&#xff0c;且品相随销售时间的增加而变差&#xff0c; 大部分品种如当日未售出&#xff0c;隔日就无法再售。因此&#xff0c;商超通常会根据各商品的历史销售和需 求情况每天进行补货。 由于商超销…

vue3.2 导出pdf文件或表格数据

要在Vue 3中导出PDF文件&#xff0c;你可以使用第三方库来处理PDF生成和导出。一个常用的库是jspdf&#xff0c;它允许你在客户端或服务器端生成PDF文档。 以下是在Vue 3中使用jspdf库导出PDF文件的基本步骤&#xff1a; 第一步首先&#xff0c;安装jspdf库。你可以使用npm或ya…

macbook如何通过命令行安装软件

作者&#xff1a;吴业亮 博客&#xff1a;wuyeliang.blog.csdn.net 通过命令行安装 macOS 上的 .dmg 文件需要进行一些额外的步骤&#xff0c;因为 .dmg 文件通常需要手动挂载和安装。下面以安装git为例。你可以按照以下步骤进行操作&#xff1a; 将下载的 dmg 文件挂载到文件…

玩转Mysql系列 - 第17篇:存储过程自定义函数详解

这是Mysql系列第17篇。 环境&#xff1a;mysql5.7.25&#xff0c;cmd命令中进行演示。 代码中被[]包含的表示可选&#xff0c;|符号分开的表示可选其一。 需求背景介绍 线上程序有时候出现问题导致数据错误的时候&#xff0c;如果比较紧急&#xff0c;我们可以写一个存储来…

亚马逊鲲鹏系统多渠道引流功能快速增加你的listing流量

如果亚马逊Listing没有流量&#xff0c;那么亚马逊产品排名也会在很靠后的位置&#xff0c;从而就会导致吸引不到客户点击进行下单购买&#xff0c;因此引流就很重要了&#xff0c;普通的引流方法很难达到效果&#xff0c;并且还会花费大量的时间&#xff0c;那么我们可以用亚马…

【postgresql 基础入门】数据库服务的管理,启动、停止、状态查看、配置加载、重启都在这里

数据库服务管理 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献&#xff1a; toadb开源库 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff…

JMeter压力测试 5分钟让你学会如何并发压测接口

文章目录 地址下载启动 使用 地址 JMeter官网下载&#xff1a;https://jmeter.apache.org/download_jmeter.cgi 下载 最新款的jmeter需要java8的支持&#xff0c;请自行安装jdk8或以上的版本 根据系统不同系统下载zip或者是tgz格式的压缩包&#xff0c;并解压&#xff0c;博…

企业互联网暴露面未知资产梳理

一、互联网暴露面梳理的重要性 当前&#xff0c;互联网新技术的产生推动着各种网络应用的蓬勃发展&#xff0c;网络安全威胁逐渐蔓延到各种新兴场景中&#xff0c;揭示着网络安全威胁不断加速泛化。当前网络存在着许多资产&#xff0c;这些资产关系到企业内部的安全情况&#…

【Chrome】chrome浏览器未连接到互联网

问题描述 电脑上安装了一个联想电脑管家&#xff0c;进行了一下清理&#xff0c;并优化了一下启动项&#xff0c;Chrome浏览器突然什么网站都无法访问了。以为更新坏了&#xff0c;但相同的网站放到火狐浏览器上&#xff0c;竟然可以打开&#xff0c;怎么回事呢&#xff1f;怎…