暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Quartz定时任务

我们家Java 2021-09-10
498

点击上方蓝色我们家Java,选择“关注


Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全用Java开发,用于执行预定任务。它类似于java.util.Timer定时器,但是它又比Timer多很多功能。


简单定时任务(内存持久化)


首先引入maven依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

定义一个接口实现计时功能(例如:定时发送邮件、提醒消息、...):

创建定时任务类QSimpleTask继承 QuzrtzJobBean :
package com.example.demo.task;

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

import java.util.Date;

public class QSimpleTask extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("简单的定时任务执行时间:" + new Date().toLocaleString());
    }
}

我们还需要编写一个配置类做触发任务执行的触发器(指定任务的运行时间、执行时间、执行间隔)
package com.example.demo.config;

import com.example.demo.task.QSimpleTask;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QSimpleConfig {
    // 指定具体的定时任务类
    @Bean
    public JobDetail uploadTaskDetail() {
        return JobBuilder.newJob(QSimpleTask.class)
                .withIdentity("QSimpleTask")
                .storeDurably().build();
    }

    @Bean
    public Trigger uploadTaskTrigger() {
        // 设定触发执行的方式,定时任务,每隔7秒执行一次
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("*/7 * * * * ?");
        // 返回任务触发器
        return TriggerBuilder.newTrigger().forJob(uploadTaskDetail())
                .withIdentity("QSimpleTask")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

之后实现Job这个简单的接口:
package com.example.demo.job;

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

public interface Job {

    // 提供上下文调度信息
    void execute(JobExecutionContext context) throws JobExecutionException;
}

运行代码,得到结果:


动态定时任务(数据库持久化)


有些定时任务执行一段时间以后就不需要了,如果在代码中进行修改然后重新打包发布,Quartz可以解决这个问题。


我们将使用Quartz提供的API完成配置任务的增删改查,将任务的配置保存在数据库中。


在application.yml文件中进行配置:
spring:
  datasource:
      url: jdbc:mysql://localhost:3306/Family?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
      driver-class-namecom.mysql.cj.jdbc.Driver
  quartz:
    # 数据库存储quartz任务配置
    job-store-type: JDBC 
    jdbc:
      # 自动初始化表结构,第一次启动的时候这里写always,之后改成NEVER
      initialize-schema: always 

创建一个定时相关的实体类并保存到数据库中去:
package com.example.demo.model;

import lombok.Data;

@Data
public class QBean {

    // 任务id
    private String id;

    // 任务名称
    private String jobName;

    // 任务执行类
    private String jobClass;

    // 任务状态
    private Integer status;

    // 任务运行时间表达式
    private String cronExpression;
}

在util文件夹下创建定时任务暂停,修改,启动,单次启动工具类:
package com.example.demo.utils;

import com.example.demo.model.QBean;
import org.quartz.*;

public class QUtils {

    @SuppressWarnings("unchecked")
    public static void createScheduleJob(Scheduler scheduler, QBean quartzBean) throws ClassNotFoundException, SchedulerException {
        // 获取到定时任务的执行类
        // 定时任务类需要是job类的具体实现 QuartzJobBean是job的抽象类
        Class<? extends Job> jobClass = (Class<? extends Job>) Class.forName(quartzBean.getJobClass());
        // 构建定时任务信息
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(quartzBean.getJobName()).build();
        // 设置定时任务执行方式
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
        // 构建触发器
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartzBean.getJobName()).withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail, trigger);
    }

    public static void pauseScheduleJob(Scheduler scheduler, String jobName) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(jobName);
        scheduler.pauseJob(jobKey);
    }

    public static void resumeScheduleJob(Scheduler scheduler, String jobName) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(jobName);
        scheduler.resumeJob(jobKey);
    }

    public static void runOnce(Scheduler scheduler, String jobName) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(jobName);
        scheduler.triggerJob(jobKey);
    }

    public static void updateScheduleJob(Scheduler scheduler, QBean quartzBean) throws SchedulerException {

        // 获取到对应任务的触发器
        TriggerKey triggerKey = TriggerKey.triggerKey(quartzBean.getJobName());
        // 设置定时任务执行方式
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzBean.getCronExpression());
        // 重新构建任务的触发器
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
        // 重置对应的job
        scheduler.rescheduleJob(triggerKey, trigger);
    }

    public static void deleteScheduleJob(Scheduler scheduler, String jobName) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(jobName);
        scheduler.deleteJob(jobKey);
    }
}

最后再编写controller代码:
package com.example.demo.controller;

import com.example.demo.model.QBean;
import com.example.demo.utils.QUtils;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
@RequestMapping("/QZ/job/")
public class QController {

    // 注入scheduler
    @Resource
    private Scheduler scheduler;

    @PostMapping("/create")
    @ResponseBody
    public String createJob(@RequestBody QBean quartzBean) throws SchedulerException, ClassNotFoundException {
        QUtils.createScheduleJob(scheduler, quartzBean);
        return "创建任务成功";
    }

    @PostMapping("/pause")
    @ResponseBody
    public String pauseJob(String jobName) throws SchedulerException {
        QUtils.pauseScheduleJob(scheduler, jobName);
        return "暂停";
    }

    @PostMapping("/run")
    @ResponseBody
    public String runOnce(String jobName) throws SchedulerException {
        QUtils.runOnce(scheduler, jobName);
        return "运行" + jobName + "成功";//这里return不是生产级别代码,测试简单写一下
    }

    @PostMapping("/resume")
    @ResponseBody
    public String resume(String jobName) throws SchedulerException {
        QUtils.resumeScheduleJob(scheduler, jobName);
        return "恢复定时任务成功:" + jobName;
    }

    @PostMapping("/update")
    @ResponseBody
    public String update(@RequestBody QBean quartzBean) throws SchedulerException {
        QUtils.updateScheduleJob(scheduler, quartzBean);
        return "更新定时任务调度信息成功";
    }
}

点击下方阅读原文,查看上一篇
文章转载自我们家Java,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论