Spring集成Quartz的3种方式

Posted 一棵代码树

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring集成Quartz的3种方式相关的知识,希望对你有一定的参考价值。

1.使用xml配置方式

Maven依赖

    <properties>
        <!-- spring版本号 -->
        <spring.version>4.2.2.RELEASE</spring.version>                      <!-- Quartz的版本 -->
    </properties>
    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.2</version>
        </dependency>

application.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置Job类 -->
    <bean id="myJob" class="cn.enjoyedu.quartz.xml.CronJob"></bean>

    <!-- 配置JobDetail -->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 执行目标job -->
        <property name="targetObject" ref="myJob"></property>

        <!-- 要执行的方法 -->
        <property name="targetMethod" value="execute"></property>
    </bean>

    <!-- 配置tirgger触发器 -->
    <bean id="cronTriggerFactoryBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!-- jobDetail -->
        <property name="jobDetail" ref="jobDetail"></property>

        <!-- cron表达式,执行时间  每5秒执行一次 -->
        <property name="cronExpression" value="0/5 * * * * ?"></property>
    </bean>

    <!-- 配置调度工厂 -->
    <bean id="springJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTriggerFactoryBean"></ref>
            </list>
        </property>

    </bean>

    <!--<bean id="simpleTrigger"  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">-->
        <!--&lt;!&ndash;配置具体要执行的jobDetail&ndash;&gt;-->
        <!--<property name="jobDetail" ref="simpleJobDetail" />-->
        <!--&lt;!&ndash;初始延迟时间 1s&ndash;&gt;-->
        <!--<property name="startDelay" value="1000" />-->
        <!--&lt;!&ndash;间隔执行时间每2s执行一次&ndash;&gt;-->
        <!--<property name="repeatInterval" value="2000" />-->
    <!--</bean>-->
</beans>

Job类

package cn.enjoyedu.quartz.xml;

public class CronJob {
    public void execute(){
        System.out.println("定时任务执行...每5秒执行一次");
    }
}

测试类

package cn.enjoyedu.quartz.xml;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringQuartzXmlTest {
    public static void main(String[] args) {
        //启动spring容器
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        System.out.println("initContext successfully");
    }
}

执行结果

initContext successfully
定时任务执行...每5秒执行一次
定时任务执行...每5秒执行一次

2.注解方式

application.xml

    <!-- 开启组件扫描 -->
    <context:component-scan base-package="cn.enjoyedu.quartz.annotation"></context:component-scan>
    <!-- 开启定时任务,spring的定时任务。不是原生quartz -->
    <task:annotation-driven/>

Job class

package cn.enjoyedu.quartz.annotation;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class AnnotationJob {
    @Scheduled(cron = "0/5 * * * * ?")
    public void excute(){
        System.out.println("AnnotationJob 执行 5秒1次");
    }
}

执行结果

initContext successfully
AnnotationJob 执行 5秒1次
AnnotationJob 执行 5秒1次

3.支持数据库配置cron表达式

3.1TimetaskController

@RequestMapping(value = "/initJob", method = RequestMethod.POST)
    @ResponseBody
    public String initJob() {
        try {
            ObjectResult result = timetaskBiz.initJob();
            return JSONHelper.toJsonDataAPI(result, result.getApiStatus(), result.getErrorMsg());
        } catch (Exception e) {
            return JSONHelper.toJsonErrorDataAPI(e);
        }
    }

3.2 初始化job和启动job

    /**
     * 初始化job
     * @param timetask
     */
    @Override
    public ObjectResult initJob() {
        ObjectResult result = new ObjectResult();
        try {
            Scheduler scheduler = factoryBean.getScheduler();
            //这里从数据库中获取任务信息数据
            Timetask timetask = new Timetask();
            //0 表示定时任务停止中  1 表示定时任务执行中
            timetask.setJobStatus("0");
            //从数据库中查询定时印务记录。
            List<Timetask> timetaskList =  this.getTimetaskListCus(timetask).getListTimetask();
            for (Timetask task : timetaskList) {
                addJob(task);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            result.setErrorMsg(e.getMessage());
            result.setApiStatus(ApiData.STATUS_EXCEPTION);
        }
        return result;
    }
    
    

     /**
     * 添加job
     * @param timetask
     */
    private void addJob(Timetask timetask) {
        if(timetask == null || (timetask.getJobStatus() == ScheduleJob.STATUS_RUNNING)) {
            return;
        }

        try {
            Scheduler scheduler = factoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(timetask.getName(),timetask.getGroupName());
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //如果不存在cronTrigger则重新创建一个
            if(null == cronTrigger){
                Class clazz = null;
                try {
                    clazz = Class.forName(timetask.getBeanClass());
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
                JobDetail  jobDetail = JobBuilder.newJob(clazz)
                        .withIdentity(timetask.getName(),timetask.getGroupName())
                        .usingJobData("data","")
                        .build();
                jobDetail.getJobDataMap().put("scheduleJob",timetask);
                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(timetask.getCron());
                cronTrigger = TriggerBuilder.newTrigger().withDescription(timetask.getIdStr())
                        .withIdentity(timetask.getName(),timetask.getGroupName())
                        .withSchedule(cronScheduleBuilder)
                        .build();

                scheduler.scheduleJob(jobDetail,cronTrigger);
            } else {

                CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(timetask.getCron());
                //TODO usingJobData的参数
                cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).usingJobData("data","")
                        .withSchedule(cronScheduleBuilder).build();
                scheduler.rescheduleJob(triggerKey,cronTrigger);
            }
            //执行
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

3.3 job类

package com.zt.uni.api.task.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob ... execute ...");
    }
}

package com.zt.uni.api.task.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob2 implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob2 ... execute ...");
    }
}

3.4 数据库配置

技术分享图片

3.5 执行结果

MyJob ... execute ...
MyJob2 ... execute ...
MyJob ... execute ...
MyJob ... execute ...
MyJob2 ... execute ...
MyJob ... execute ...
MyJob ... execute ...

3.6 存在的问题(最近工作忙,后面再补回来)

  • 如果要支持定时任务可以拔插式使用
  • 要支持图形界面配置
  • 要支持定时任务在某个时间段期间执行[start_time ,end_time]执行
  • 要支持记录定时任务的异常信息

以上是关于Spring集成Quartz的3种方式的主要内容,如果未能解决你的问题,请参考以下文章

spring集成Quartz时区问题造成任务晚执行八小时

Spring Boot 入门:集成Quartz定时任务

SpringBoot2.6.3集成quartz

SpringBoot2.6.3集成quartz

Quartz总结:Quartz集成Spring的2个方法

SpringBoot2.6.3集成quartz