Spring定时服务QuartZ原理及代码案例

  在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等。

  我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但时调度控制非常不方便,并且我们需要大量的代码。

  使用Quartz框架无疑是非常好的选择,并且与Spring可以非常方便的集成。

  Spring提供了支持时序调度的整合类。整个构建任务调度服务需要三步:

  1)向项目中添加jar包:添加quartz.jar包,将他加到你工程的classpath中去。

  2)写Class文件,在文件中定义你要执行操作的函数你就可以通过配置来达到定时操作了。

  3)提供applicationContext.xml Spring配置文件,其中配置你的定时发送操作以及设置定时器的各种属性(包括运行频率和初始运行时机)。 

  小编做了一个每5秒打印一次当前时间的例子,具体请参考源码,尤其注意配置文件的写法。(详见下面“示例”)

什么是Quartz?

  Quartz是一个强大的企业级任务调度框架。它允许开发人员灵活地定义触发器的调度时间表,并可对触发器和任务进行关联映射。此外,Quartz提供了调度运行环境的持久化机制,可以保存并会发调度现场,即使系统因故障关闭,任务调度现场数据并不会丢失。Spring中继承并简化了Quartz。

如何使用Quartz?

  对于Quartz,我们使用的时候主要是注重两个方面,一个是定时任务的业务,另一个就是Cron表达式。

  1>Quartz存在两种方式来定义定时执行任务,一种是使用QuartJobBean和JobDetailBean;另一种是使用MethodInvokingJobDetailFactoryBean。

  2>Cron表达式包括下面7个字段并区别顺序:秒0-59,分0-59,小时0-23,月内日期1-31,月1-12或者JAN-DEC,周内日期1-7或者SUN-SAT,年(可选字段)留空或者1970-2099并且通过特殊字符表示特殊意义,具体为下:

  • 斜线(/)字符表示增量值。例如,在秒字段中"5/15"代表从第5秒开始,每15秒一次。
  • 问号(?)字符和字母L字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入"?",表示周内日期值无关紧要。这里有个很蛋疼的设定,无关Quartz,而是Spring集成Quartz后,它自己加的一个约束,那就是:日期(1-31)和星期(SUN-SAT)两者,必须有一个是问号(?),系统在启动的时候,Spring会检查表达式,如果不符合它的规则,就会抛异常。所以在使用的时候这个地方一定要注意,而这个在Linux上执行Cron是没有这个限制的。
  • 字母L字符是last的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果"L"单独存在,就等于"7",否则代表当月内周内日期的最后一个实例。所以"0L"表示安排在当月的最后一个星期日执行。
  • 字母(W)字符把执行安排在最靠近指定值的工作日。把"1W"放在月内日期字段中,表示把执行安排在当月的第一个工作日内。
  • 井号(#)字符为给定月份指定具体的工作日实例。把"MON#2"放在周内日期字段中,表示把任务安排在当月的第二个星期一。
  • 星号(*)字符是通配字符,表示该字段可以接受任何可能的值、表达式例子。

例子:

      "0 0 08 * * ?" 每天上午8点触发
      "0 15 10 ? * *" 每天上午10:15触发
      "0 15 10 * * ?" 每天上午10:15触发
      "0 15 10 ? * 6L 2009-2019" 2009年至2019年的每月的最后一个星期五上午10:15触发
      "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

【示例】

  我们使用Spring定时服务Quartz来实现一个每5秒打印一次当前时间的小例子。

  1:定义接口IPrintInfoService类

package demoinfo.spring.quartz;
public interface IPrintInfoService {
  public void print();
}

  2:实现接口类PrintInfoServiceImpl

package demoinfo.spring.quartz;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import demoinfo.spring.quartz.IPrintInfoService;

public class PrintInfoServiceImpl implements IPrintInfoService{

  public void print() {
    Calendar now = Calendar.getInstance();
    System.out.println("现在是北京时间:" + this.format(now.getTime()));
  }

  public String format(Date date){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
  }

}

  3:基于QuartzJobBean的实现类PrintInfoJob

package demoinfo.spring.quartz;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import demoinfo.spring.quartz.IPrintInfoService;

public class PrintInfoJob extends QuartzJobBean{

  private IPrintInfoService prinfInfoService = null;
  public IPrintInfoService getPrinfInfoService() {
    return prinfInfoService;
  }
  public void setPrinfInfoService(IPrintInfoService prinfInfoService) {
    this.prinfInfoService = prinfInfoService;
  }
  @Override
  protected void executeInternal(JobExecutionContext arg0)
      throws JobExecutionException {
    this.prinfInfoService.print();
  }
}

  4:Spring配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

  <bean id="printInfoService" class="demoinfo.spring.quartz.PrintInfoServiceImpl" />
  <!-- 配置一个Job -->
  <bean id="printInfoJob" class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass" value="demoinfo.spring.quartz.PrintInfoJob" />
    <property name="jobDataAsMap">
      <map>
        <entry key="prinfInfoService" value-ref="printInfoService"></entry>
      </map>
    </property>
  </bean>

  <!-- 简单的触发器 -->
  <bean id="simplePrintInfoTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail">
      <ref bean="printInfoJob" />
    </property>
    <property name="startDelay">
      <value>6000</value>
    </property>
    <property name="repeatInterval">
      <value>6000</value>
    </property>
  </bean>

  <!--复杂的触发器 -->
  <bean id="complexPrintInfoTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail">
      <ref bean="printInfoJob" />
    </property>
    <property name="cronExpression">
      <value>00,05,10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
    </property>
  </bean>

  <!-- spring触发工厂 -->
  <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
      <list>
        <ref bean="complexPrintInfoTrigger" />
      </list>
    </property>
  </bean>
</beans>

  5:测试用例类SpringQuartzDemo

package demoinfo.spring.quartz;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringQuartzDemo {

  public static void main(String[] args) {
    System.out.println("测试开始......");
    new ClassPathXmlApplicationContext(
        "classpath:demoinfo/spring/quartz/applicationContext.xml");
    System.out.println("测试结束......");
  }

}

  运行测试用例,可以看到控制台每过5秒钟就打印一次时间信息。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot整合quartz产生错误及解决方案

    1.spring boot整合quartz执行多个定时任务时报: org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'group1.job1', because one already exists with this identification. 定时任务虽然执行,但报了错误.第一次执行时没有报错误,第二次及之后执行前会报这个错误, 解决办法: 在初始化调度的时候clean一下: scheduler.clear();

  • spring boot + quartz集群搭建的完整步骤

    quartz集群能力: quartz集群分为水平集群和垂直集群,水平集群即将定时任务节点部署在不同的服务器,水平集群最大的问题就是时钟同步问题, quartz集群强烈要求时钟同步,若时钟不能同步,则会导致集群中各个节点状态紊乱,造成不可预知的后果,请自行搜索服务器时钟同步, 若能保证时钟同步,水平集群能保证服务的可靠性,其中一个节点挂掉或其中一个服务器宕机,其他节点依然正常服务:垂直集群则是集群各节点部署在同一台服务器, 时钟同步自然不是问题,但存在单点故障问题,服务器宕机会严重影响服务的可用性

  • springboot Quartz动态修改cron表达式的方法

    1.概述: 在开发中有的时候需要去手动禁止和启用定时任务,修改定时任务的cron表达式然后再让其动态生效,之前有过SSM的类似的业务的开发但是忘记写下来了...只好重新温习了一次,加上最近比较流行springBoot所以升级了一下用springBoot来完成. 2.关联技术 SpringBoot.Quartz.H2.thymeleaf (好像就这么多) 3.具体流程 1)首先去手动创建一个调度器工厂对象-SchedulerFactoryBean;其实应该不用手动创建的但是为了顾及到业务的复杂性所

  • SpringBoot与Quartz集成实现分布式定时任务集群的代码实例

    Spring Boot与Quartz集成实现分布式定时任务集群 直接贴代码 POM <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs

  • Quartz+Spring Boot实现动态管理定时任务

    项目实践过程中碰到一个动态管理定时任务的需求:针对每个人员进行信息的定时更新,具体更新时间可随时调整.启动.暂定等. 思路 将每个人员信息的定时配置保存到数据库中,这样实现了任务的动态展示和管理.任务的每一次新增或变更,都会去数据库变更信息. 设置一个统一的任务管理器,专门负责动态任务的增删改查. POM依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mav

  • SpringBoot集成Quartz实现定时任务的方法

    1 需求 在我的前后端分离的实验室管理项目中,有一个功能是学生状态统计.我的设计是按天统计每种状态的比例.为了便于计算,在每天0点,系统需要将学生的状态重置,并插入一条数据作为一天的开始状态.另外,考虑到学生的请假需求,请假的申请往往是提前做好,等系统时间走到实际请假时间的时候,系统要将学生的状态修改为请假. 显然,这两个子需求都可以通过定时任务实现.在网上略做搜索以后,我选择了比较流行的定时任务框架Quartz. 2 Quartz Quartz是一个定时任务框架,其他介绍网上也很详尽.这里要介

  • Springboot整个Quartz实现动态定时任务的示例代码

    简介 Quartz是一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行.每天凌晨执行.每周五执行等等,还支持分布式调度.本文使用Springboot+Mybatis+Quartz实现对定时任务的增.删.改.查.启用.停用等功能.并把定时任务持久化到数据库以及支持集群. Quartz的3个基本要素 Scheduler:调度器.所有的调度都是由它控制. Trigger: 触发器.决定什么时候来执行任务. JobDetail & Job: JobDetail定义的是任务数据,而真正的

  • springboot+quartz以持久化的方式实现定时任务的代码

    这篇文章给大家介绍springboot+quartz以持久化的方式实现定时任务,详情如下所示: 篇幅较长,耐心的人总能得到最后的答案小生第一次用quartz做定时任务,不足之处多多谅解. 首先 在springboot项目里做定时任务是比较简单的,最简单的实现方式是使用**@Scheduled注解,然后在application启动类上使用@EnableScheduling**开启定时任务. 示例 @SpringBootApplication @EnableScheduling public cla

  • 浅谈SpringBoot集成Quartz动态定时任务

    SpringBoot自带schedule 沿用的springboot少xml配置的优良传统,本身支持表达式等多种定时任务 注意在程序启动的时候加上@EnableScheduling @Scheduled(cron="0/5 * * * * ?") public void job(){ System.out.println("每五秒执行一次"); } 为什么要使用Quartz 多任务情况下,quartz更容易管理,可以实现动态配置 执行时间表达式: 表达式示例: 集成

  • Spring定时服务QuartZ原理及代码案例

    在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等. 我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但时调度控制非常不方便,并且我们需要大量的代码. 使用Quartz框架无疑是非常好的选择,并且与Spring可以非常方便的集成. Spring提供了支持时序调度的整合类.整个构建任务调度服务需要三步: 1)向项目中添加jar包:添加quartz.jar包,将他加到你工程的classpath中去. 2

  • Springmvc数据格式化原理及代码案例

    1.简介 Converter可以将一种类型转换成另一种类型,是任意Object之间的类型转换. Formatter则只能进String与任意Object对象的转换,它提供解析与格式化两种功能 解析:将String类型字符串转换为任意Objec对象, 格式化:将任意Objec对象转换为字符串进行格式化显示. 使用Formatter 实现Formatter接口定义一个类,T为要解析得到或进行格式化的数据类型. 在类中实现两个方法 String print(T t,Locale locale):把T类

  • 代码分析Spring MVC的工作原理

    遗留问题 在关于利用maven搭建ssm的博客,我们一起来探讨下问的最多的问题中,我遗留了一个问题:Spring mvc是何时.何地.如何将Model中的属性绑定到哪个作用域,这里的作用域指的是Servlet的四大作用域:不了解问题背景的可以回过头去看看我的上篇博文. 明确的解答我会放到最后,在解答问题之前,我先和大家一起来捋一捋Spring mvc的工作原理.废话不多说,开始我们神秘的探险之旅! 应用示例 在讲工作原理之前,我们先看一个简单的spring mvc(ssm)示例,以及实现的效果

  • 深入了解Spring控制反转IOC原理

    目录 一.什么是Spring IOC容器 二.IOC有哪些优点 三.控制反转(IOC)有什么作用 四.IoC和DI有什么区别 五.Spring IoC的实现机制 六.IoC支持哪些功能 七.BeanFactory和ApplicationContext有什么区别 八.ApplicationContext通常的实现是什么 九.依赖注入的方式,构造器依赖注入和 Setter方法注入的区别 十.依赖注入的基本原则和优点 一.什么是Spring IOC容器 Spring是包含众多工具的IoC容器,控制反转

  • Spring 中使用Quartz实现任务调度

    前言:Spring中使用Quartz 有两种方式,一种是继承特定的基类:org.springframework.scheduling.quartz.QuartzJobBean,另一种则不需要,(推荐使用第二种).下面分别介绍. 1.作业类继承 org.springframework.scheduling.quartz.QuartzJobBean 第一步:定义作业类 java代码 import java.text.SimpleDateFormat; import java.util.Date; i

  • Spring Boot整合Elasticsearch实现全文搜索引擎案例解析

    简单说,ElasticSearch(简称 ES)是搜索引擎,是结构化数据的分布式搜索引擎.Elastic Search是一个开源的,分布式,实时搜索和分析引擎.Spring Boot为Elasticsearch及Spring Data Elasticsearch提供的基于它的抽象提供了基本的配置.Spring Boot提供了一个用于聚集依赖的spring-boot-starter-data-elasticsearch 'StarterPOM'. 引入spring-boot-starter-dat

  • Spring实现处理跨域请求代码详解

    一次正常的请求 最近别人需要调用我们系统的某一个功能,对方希望提供一个api让其能够更新数据.由于该同学是客户端开发,于是有了类似以下代码. @RequestMapping(method = RequestMethod.POST, value = "/update.json", produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody Contacter update(@RequestBody Contacter

  • 浅谈Spring Cloud Ribbon的原理

    Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起.Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等.简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器.我们也很容易使用Ribbon实现自定义的负载均衡算法. 说起负载均衡一般都会想到服务端的负载均衡,常用产品包括LBS硬件或云服务.Nginx等,都是

  • Spring Cloud 负载均衡器 Ribbon原理及实现

    Ribbon简介 分布式系统中,各个微服务会部署多个实例,如何将服务消费者均匀分摊到多个服务提供者实例上,就要使用到负载均衡器 Ribbon 是负载均衡器 ,它提供了很多负载均衡算法,例如轮询.随即等,在配置服务提供者地址后,可以将服务消费者请求均匀的分发 为服务消费者整合Ribbon 添加 Ribbon 依赖库 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri

  • Spring Validation方法实现原理分析

    最近要做动态数据的提交处理,即需要分析提交数据字段定义信息后才能明确对应的具体字段类型,进而做数据类型转换和字段有效性校验,然后做业务处理后提交数据库,自己开发一套校验逻辑的话周期太长,因此分析了Spring Validation的实现原理,复用了其底层花样繁多的Validator,在此将分析Spring Validation原理的过程记录下,不深入细节 如何使用Spring Validation Spring Bean初始化时校验Bean是否符合JSR-303规范 1.手动添加BeanVali

随机推荐