zoukankan      html  css  js  c++  java
  • spring与quartz的整合

    使用方法

    quartz是一个强大的任务调度框架,利用spring将其整合,添加较少的配置即可快速使用,主要步骤如下:

    0. 导入需要的jar包或添加依赖,主要有spring-context-support、spring-tx、quartz;

    1. 编写被调度类和被调度方法,即需要定时执行的类和方法;

    2. 在spring容器中注册被调度类,单个注册或包扫描均可;

    3. 在spring容器中注册作业类(MethodInvokingjOBdetailFactoryBean),并注入被调度类和被调度方法,一般每个被调度方法需要注册一个作业类;

    4. 在spring容器中注册触发器,并注入对应的作业类和触发条件,一般每个作业类需要注册一个触发器;

    触发器是用来指定被调度方法的执行时间的,根据触发条件的不同,有两个类可以选择:

    (1) SimpleTriggerFactoryBean,只能指定间隔固定时长执行,例如每隔5秒钟执行一次;

    (2) CronTriggerFactoryBean,既可以指定间隔固定时长执行,也可以指定某个或某几个时刻执行,例如每周三下午16点;

    5. 在spring容器中注册调度工厂(ScheduerFactoryBean),并注入需要的触发器,可以注入一个或多个触发器。

    示例Demo

    被调度类和被调度方法 

    /**
     * 使用quartz框架实现定时任务
     * 被调度类
     * created on 2019-04-20
     */
    public class QuartzJob {
    
        /**
         * 定时方法,使用固定时长指定执行时间
         */
        public void doSimpleBusiness() {
            //业务逻辑省略,仅测试能执行方法
            System.out.println("----------quartz + 固定时长----------");
        }
    
        /**
         * 定时方法,使用cron表达式指定执行时间
         */
        public void doCronBusiness() {
            //业务逻辑省略,仅测试能执行方法
            System.out.println("----------quartz + cron表达式----------");
        }
    
    }

    spring配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--注册被调度类-->
        <bean id="quartzJob" class="cn.monolog.diana.quartz.QuartzJob" />
    
        <!--注册固定时长的作业类,并注入被调度类和被调度方法-->
        <bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject" ref="quartzJob" />
            <property name="targetMethod" value="doSimpleBusiness" />
        </bean>
    
        <!--注册固定时长的触发器,并注入相应的作业类和间隔时间(单位为毫秒)-->
        <bean id="trigger1" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
            <property name="jobDetail" ref="jobDetail1" />
            <property name="repeatInterval" value="3000" />
        </bean>
    
        <!--注册cron表达式的作业类,并注入被调度类和被调度方法-->
        <bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject" ref="quartzJob" />
            <property name="targetMethod" value="doCronBusiness" />
        </bean>
    
        <!--注册cron表达式的触发器,并注入相应的作业类和cron表达式-->
        <bean id="trigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" ref="jobDetail2" />
            <property name="cronExpression" value="0/4 * * * * ?" />
        </bean>
    
        <!--注册调度工厂,并注入需要生效的触发器,注意最后autowire的配置-->
        <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">
            <property name="triggers">
                <list>
                    <ref bean="trigger1" />
                    <ref bean="trigger2" />
                </list>
            </property>
        </bean>
    
    </beans>

    踩过的坑

    1. 一开始只是添加了spring-context-support和quartz依赖,结果服务启动失败,异常日志如下:

    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactory' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.quartz.SchedulerFactoryBean]: No default constructor found; nested exception is java.lang.NoClassDefFoundError: org/springframework/transaction/TransactionException
    乍一看是因为初始化ScheduerFactoryBean失败,因为没有默认的构造器,后面又说是没有关于TransactionException的定义。但是我这个demo并没有用到事务,跟TransactionException有啥关系?暂时找不到内在联系,但是既然提示了,就加关于事务的依赖试一下。果然,添加了spring-tx的依赖之后,服务启动成功。至于为什么初始化ScheduerFactoryBean需要用到事务,待日后找到答案再来更新。

    2. 一开始在配置文件中注册调度工厂并没有加autowire属性,启动服务时报错,无法启动quartz触发器,因为表不存在,异常日志如下:

    com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'sm4_console.QRTZ_TRIGGERS' doesn't exist

    参考了这位大神的博文https://www.cnblogs.com/gmq-sh/p/4328317.html,大概意思是quartz会使用数据库记录被调度类的状态,而数据库中并不存在这些日志表。解决方法就是在配置文件注册调度工厂时加autowire属性配置。

    其他整合方案

    除了上述,spring还提供了另外一种整合quartz的方案,即被调度类需要继承QuartzJobBean类,其他配置方式类似。

    但是这种方案显然不如第一种灵活,因为被调度类需要继承固定的类,而Java又是单继承……

  • 相关阅读:
    链表与顺序表
    js对table的动态操作
    关于float的内部结构
    spring bean的生命周期
    浅谈(吐槽)自己
    java缓存机制(上)
    Verilog经典输入控制/激励信号模板1
    verilog中的for循环问题
    2015,welcome!!!
    (转)Quartus II和Modelsim的联合仿真(详细)
  • 原文地址:https://www.cnblogs.com/dubhlinn/p/10744833.html
Copyright © 2011-2022 走看看