SSM的quartz动态定时器

Posted noire

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSM的quartz动态定时器相关的知识,希望对你有一定的参考价值。

Controller层:

package com.smartteam.controller;

import com.smartteam.controller.BaseController;
import com.smartteam.service.SampleTryEntryService;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author XiaoDeng
 * @since 2019-08-06
 */
@Api(tags = "动态定时器")
@RestController
@RequestMapping("/sampleTry")
public class SampleTryController extends BaseController 
    
    @Autowired
    private SampleTryEntryService sampleTryEntryService;
    
    /**
     * 逻辑处理
     */
    public void sampleTryEntity()
        // 逻辑处理之后启动定时任务
        sampleTryEntryService.scrhySendMessage();            
    
    

SampleTryEntryService层:

package com.smartteam.service;

import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author XiaoDeng
 * @since 2019-08-06
 */
public interface SampleTryEntryService extends IService<SampleTryEntry> 
    
    /**
     * 逻辑处理之后启动定时任务
     */
    void scrhySendMessage();

SampleTryEntryServiceImpl层:

package com.smartteam.service.impl;

import com.smartteam.common.DateUtil;
import com.smartteam.common.quartz.CronUtils;
import com.smartteam.common.quartz.QuartzManager;
import com.smartteam.mapper.erp.SampleTryEntryMapper;
import com.smartteam.service.SampleTryEntryService;
import com.smartteam.vo.quartz.QuartzVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author XiaoDeng
 * @since 2019-08-06
 */
@Service
public class SampleTryEntryServiceImpl extends ServiceImpl<SampleTryEntryMapper, SampleTryEntry> implements SampleTryEntryService 

    /**
     * 判断定时任务是否开启
     */
    public boolean startQuartz = false;
    /**
     * new一个定时器
     */
    QuartzManager quartz = new QuartzManager();
    /**
     * 保存定时任务要用到的信息
     */
    public static List<Map<String, Object>> scymaps = new ArrayList<>();
    
    /**
     * 逻辑处理之后启动定时任务
     */
    @Override
    public void scrhySendMessage() 
        // 把计划回收日期小于当前日期的数据的发送消息状态设置为1(防止服务断掉的时候,导致发送消息失败)
        QueryWrapper<SampleTryEntry> wrapper = new QueryWrapper<>();
        wrapper.eq("SENDOUT", 0);
        wrapper.lt("FSAMPLERECOVERYD", new Date());
        List<SampleTryEntry> tryEntries = list(wrapper);
        for (SampleTryEntry entry : tryEntries) 
            entry.setSendout(1);
            updateEntry(entry);
        
        // 获取定时任务要用到的信息
        List<Map<String, Object>> maps = this.baseMapper.trialWearerData();
        scymaps = maps;
        // 移除定时任务
        if(startQuartz == true)
            try 
                quartz.removeJob("定时任务提醒", "System");
             catch (SchedulerException e) 
                e.printStackTrace();
            
        else
            // 开启定时任务
            quartz.start();
            startQuartz = true;
        
        if(maps.size() > 0)
            // 时间都是一样的:比如有6行数据,每行数据FSAMPLERECOVERYD的值都一样
            String fsamplerecoveryd = maps.get(0).getOrDefault("FSAMPLERECOVERYD", "").toString();
            // 把日期转化为cron表达式
            String crontime = CronUtils.getCron(DateUtil.parseTime(fsamplerecoveryd, "yyyy-MM-dd HH:mm:ss"));
            // 添加定时任务
            QuartzVo vo = new QuartzVo();
            vo.setClassName("com.smartteam.quartz.YygQuartzJob");
            vo.setJobName("定时任务提醒");
            vo.setJobGroup("System");
            vo.setCronExpression(crontime);
            quartz.addJob(vo);
        
    

CronUtils类:日期转换cron表达式

package com.smartteam.common.quartz;

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

/**
 * 日期转换cron表达式
 * @author Administrator
 *
 */
public class CronUtils 

    //"ss mm HH dd MM ? yyyy"
    private static final SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ?");

    /***
     *  功能描述:日期转换cron表达式
     * @param date
     * @return
     */
    public static String formatDateByPattern(Date date) 
        String formatTimeStr = null;
        if (Objects.nonNull(date)) 
            formatTimeStr = sdf.format(date);
        
        return formatTimeStr;
    

    /***
     * convert Date to cron, eg "0 07 10 15 1 ?"
     * @param date  : 时间点
     * @return
     */
    public static String getCron(Date date) 
        return formatDateByPattern(date);
    

定时任务管理器QuartzManager:

package com.smartteam.common.quartz;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

import com.smartteam.vo.quartz.QuartzVo;

/**
 * 定时任务管理器
 * @author Administrator
 *
 */
public class QuartzManager 

    private Logger log = LogManager.getLogger(QuartzManager.class);

    private Scheduler scheduler = null;

    /**
     * 初始化调度器 
     */
    public QuartzManager() 
        try 
            scheduler = new StdSchedulerFactory().getScheduler();
            log.info("初始化调度器 ");
         catch (SchedulerException ex) 
            log.error("初始化调度器=> [失败]:" + ex.getLocalizedMessage());
        
    
    //初始化启动任务
    public void initJob()
        this.start();
    

     /**
      * 添加定时任务<br/>
      * className:时间到了要执行的类名:com.information.quartz.YygQuartzJob<br/>
      * jobName:自定义任务名:定时任务提醒<br/>
      * jobGroup:自定义组名:System<br/>
      * cronExpression:cron定时表达式:00 16 18 18 06 ?<br/>
      * @param record
      */
    public void addJob(QuartzVo vo)
        String className = vo.getClassName();
        String name = vo.getJobName();
        String group = vo.getJobGroup();
        String cronExpression = vo.getCronExpression();
        this.addJob(name, group, className, cronExpression);
    
    public void addJob(String name, String group, String className, String cronExpression) 
        Class<? extends Job> jobClazz = null;
        try 
            jobClazz = Class.forName(className).asSubclass(Job.class);
         catch (Exception e) 
            log.error(className+"没有继承job,e=="+e);
        
        JobDataMap map = new JobDataMap();
        addJob(name,group,jobClazz,cronExpression,map);
    
    public void addJob(String name, String group, Class<? extends Job> jobClazz, String cronExpression,JobDataMap map) 
        try 
            // 构造任务
            JobDetail job = newJob(jobClazz).withIdentity(name, group).usingJobData(map).build();
            // 构造任务触发器
            Trigger trg = newTrigger().withIdentity(name, group).withSchedule(cronSchedule(cronExpression)).build();
            // 将作业添加到调度器
            scheduler.scheduleJob(job, trg);
            log.info("创建作业=> [作业名称:" + name + " 作业组:" + group + "] ");
         catch (SchedulerException e) 
            e.printStackTrace();
            log.error("创建作业=> [作业名称:" + name + " 作业组:" + group + "]=> [失败]");
        
    
    
    /**
     * 移除定时任务
     * @param name
     * @param group
     * @throws SchedulerException
     */
    public void removeJob(String name, String group) throws SchedulerException 
            TriggerKey tk = TriggerKey.triggerKey(name, group);
            scheduler.pauseTrigger(tk);// 停止触发器
            scheduler.unscheduleJob(tk);// 移除触发器
            JobKey jobKey = JobKey.jobKey(name, group);
            scheduler.deleteJob(jobKey);// 删除作业
            log.info("删除作业=> [作业名称:" + name + " 作业组:" + group + "] ");
    

    /**
     * 启动定时任务
     */
    public void start() 
        try 
            scheduler.start();
            log.info("启动调度器 ");
         catch (SchedulerException e) 
            e.printStackTrace();
            log.error("启动调度器=> [失败]");
        
    

    /**
     * 关闭定时任务
     */
    public void shutdown() 
        try 
            scheduler.shutdown();
            log.info("停止调度器 ");
         catch (SchedulerException e) 
            e.printStackTrace();
            log.error("停止调度器=> [失败]");
        
    

定时任务管理器用到的自定义QuartzVo:

package com.smartteam.vo.quartz;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;


/**
 * @description:
 * @program: midplatform-privilege
 * @author: XiaoDeng
 * @created: 2019-08-06
 **/
@Data
@ApiModel
public class QuartzVo implements Serializable 

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "时间到了要执行的类名:com.information.quartz.YygQuartzJob")
    private String className;

    @ApiModelProperty(value = "自定义任务名:定时任务提醒")
    private String jobName;

    @ApiModelProperty(value = "自定义组名:System")
    private String jobGroup;

    @ApiModelProperty(value = "cron定时表达式:00 16 18 18 06 ?")
    private String cronExpression;

时间到了,跳转的的YygQuartzJob类:

package com.smartteam.quartz;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import com.smartteam.common.quartz.QuartzServletContextListener;
import com.smartteam.service.SampleTryEntryService;
import com.smartteam.service.impl.SampleTryEntryServiceImpl;

/**
 * 动态定时器
 * @author Administrator
 *
 */
@Component
public class YygQuartzJob implements Job 
    
    
    @Override
    public void execute(JobExecutionContext jobContext) throws JobExecutionException 
        // 定时任务quartz的job中注入service为null解决方案
        ServletContext context = null;
        try 
            context = (ServletContext) jobContext.getScheduler().getContext()
                    .get(QuartzServletContextListener.MY_CONTEXT_NAME);
         catch (SchedulerException e1) 
            e1.printStackTrace();
        
        WebApplicationContext cxt = (WebApplicationContext) context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
        SampleTryEntryService sampleTryEntryService = (SampleTryEntryService) cxt.getBean("sampleTryEntryServiceImpl");
        // 定时任务要用到的信息
        List<Map<String, Object>> maps = SampleTryEntryServiceImpl.scymaps;
        ................逻辑处理................
        // 这里重新调用定时任务的方法,业务需求
        ampleTryEntryService.scrhySendMessage();
    
    

QuartzServletContextListener类:定时任务quartz的job中注入service为null解决方案

package com.smartteam.common.quartz;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;

import org.quartz.SchedulerException;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;

/**
 * 定时任务quartz的job中注入service为null解决类QuartzServletContextListener
 * @author Administrator
 *
 */
@Component
public class QuartzServletContextListener extends QuartzInitializerListener 

    public static final String MY_CONTEXT_NAME = "servletContext";
     
    @Override
    public void contextDestroyed(ServletContextEvent sce) 
        // TODO Auto-generated method stub
        super.contextDestroyed(sce);
    
 
    @Override
    public void contextInitialized(ServletContextEvent sce) 
        // TODO Auto-generated method stub
        super.contextInitialized(sce);
        ServletContext servletContext = sce.getServletContext();
        StdSchedulerFactory factory = (StdSchedulerFactory) servletContext
                .getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY);
        try 
            factory.getScheduler().getContext()
                    .put(QuartzServletContextListener.MY_CONTEXT_NAME, servletContext);
         catch (SchedulerException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    

maven依赖:

<!-- quartz定时任务 -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>

 

以上是关于SSM的quartz动态定时器的主要内容,如果未能解决你的问题,请参考以下文章

Spring整合Quartz实现动态定时器

Spring整合Quartz实现动态定时器

Quartz总结:动态修改定时器二

Quartz实现动态定时任务

SpringBoot整合Quartz实现动态的创建或删除定时任务并将定时调度任务持久化到MySQL以及Quartz集群配置

SpringBoot集成Quartz动态定时任务