springmvc verwendet Quarz für geplante Aufgaben

springmvc verwendet Quarz für geplante Aufgaben

Projektanforderungen

1. Geplante Aufgaben
2. Geplante Aufgaben können dynamisch hinzugefügt, geändert und gelöscht werden

Glaspaket

<!-- 定时器quartz使用jar包-->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>

Java-Implementierungsklasse

1. Die Job-Factory-Instanzmethode überschreibt QuartzJobFactory

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

@Component
public class QuartzJobFactory extends AdaptableJobFactory {
    
    

    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;

    /**
     * 重写job实例化方法
     * 将实例化对象手动添加到spring IOC容器并完成对象注入
     *
     * @param bundle
     * @return
     * @throws Exception
     */
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
    
    
        //父类方法调用
        Object jobInstance = super.createJobInstance(bundle);
        //spring注入
        autowireCapableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

2. Timer-Zentralprozessor QuartzManager

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class QuartzManager {
    
    

    private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    @Autowired
    private QuartzJobFactory quartzJobFactory;

    /**
     * 新增一个定时任务
     *
     * @param jobName          任务名
     * @param jobGroupName     任务组名
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param jobClass         任务类
     * @param cron             时间设置
     * @param jobDataMap       任务参数
     */
    @SuppressWarnings("unchecked")
    public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String cron, JobDataMap jobDataMap) {
    
    
        //调度类获取
        Scheduler scheduler = null;
        try {
    
    
            scheduler = schedulerFactory.getScheduler();
            //设置job实例工厂【实现手动spring注入】
            scheduler.setJobFactory(quartzJobFactory);

            //job实例与设置其所属身份
            JobDetail jobDetail = JobBuilder.newJob(jobClass).usingJobData(jobDataMap).withIdentity(jobName, jobGroupName).build();
            //触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            //触发器身份所属设置
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();

            // 调度容器设置JobDetail和Trigger
            scheduler.scheduleJob(jobDetail, trigger);
            //启动
            if (!scheduler.isShutdown()) {
    
    
                scheduler.start();
            }
            System.out.println("新增定时任务=【" + jobName + "=" + jobGroupName + "】" + cron);
        } catch (SchedulerException e) {
    
    
            e.printStackTrace();
            System.out.println("新增定时任务【" + jobName + jobGroupName + "】失败");
        }
    }


    /**
     * 修改定时任务触发时间
     *
     * @param jobName          任务名
     * @param jobGroupName     任务组名
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     * @param cron             时间
     */
    public void modifyJobTime(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String cron) {
    
    
        Scheduler scheduler = null;
        try {
    
    
            scheduler = schedulerFactory.getScheduler();
            //获取触发器所属key
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //如果触发器不存在,不往下执行
            if (trigger == null) {
    
    
                return;
            }
            //获取当前执行时间
            String cronExpression = trigger.getCronExpression();
            //新触发器时间与旧触发器时间不一致时修改触发器时间
            if (!cronExpression.equals(cron)) {
    
    
                /** 方式一 :调用 rescheduleJob 开始 */
                // 触发器
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                // 触发器名,触发器组
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                // 触发器时间设定
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                // 创建Trigger对象
                trigger = (CronTrigger) triggerBuilder.build();
                // 方式一 :修改一个任务的触发时间(覆盖旧数据)
                scheduler.rescheduleJob(triggerKey, trigger);
                /** 方式一 :调用 rescheduleJob 结束 */

                /** 方式二:先删除,然后在创建一个新的Job  */
                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class<? extends Job> jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先删除,然后在创建一个新的Job */
                System.out.println("更新定时任务=【" + jobName + "=" + jobGroupName + "】" + cron);
            }
        } catch (SchedulerException e) {
    
    
            e.printStackTrace();
            System.out.println("更新定时任务【" + jobName + jobGroupName + "】失败");
        }

    }

    /**
     * 移除一个定时任务
     *
     * @param jobName          任务名
     * @param jobGroupName     任务组名
     * @param triggerName      触发器名
     * @param triggerGroupName 触发器组名
     */
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
    
    
        Scheduler scheduler = null;
        try {
    
    
            scheduler = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);// 停止触发器
            scheduler.unscheduleJob(triggerKey);// 移除触发器
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
            System.out.println("移除定时任务=【" + jobName + "=" + jobGroupName + "】");
        } catch (SchedulerException e) {
    
    
            e.printStackTrace();
            System.out.println("移除定时任务【" + jobName + jobGroupName + "】失败");
        }
    }

    /**
     * 启动所有定时任务
     */
    public void startJobs() {
    
    
        try {
    
    
            Scheduler scheduler = schedulerFactory.getScheduler();
            scheduler.start();
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

    /**
     * 关闭所有定时任务
     */
    public void shutdownJobs() {
    
    
        try {
    
    
            Scheduler scheduler = schedulerFactory.getScheduler();
            if (!scheduler.isShutdown()) {
    
    
                scheduler.shutdown();
            }
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }
}

3 Benutzerdefinierte geplante Aufgabenklasse (spezifischer Ausführungsinhalt)

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

@Component
public class ReminderJob implements Job {
    
    

    @Autowired
    private EduScheduleService eduScheduleService;

    /**
     * 任务执行内容
     *
     * @param jobExecutionContext
     */
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
    
    
        //参数获取
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        //逻辑代码编写
    }
}

4. Anwendungsbeispiele

import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

/**
 * @author ljc
 * @Title:
 * @Package
 * @Description: 启动监听类【项目启动完成或刷新完成时触发】
 * @date 2021/3/116:16
 */
@Service
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
    
    
    @Autowired
    private QuartzManager quartzManager;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
    
    
    	String cron = "0 0 12 * * ?";
    	JobDataMap dataMap = new JobDataMap();
        dataMap.put("testName", "a");
		quartzManager.addJob("a", "a1", "b", "b1", ReminderJob.class, cron, dataMap);
    }
}

Detaillierte Erläuterung der Cron-AusdrückeLink

5. Fehler werden gefunden, wenn das Projekt gestoppt wird

Die Webanwendung [edu_api] scheint einen Thread mit dem Namen [DefaultQuartzScheduler_Worker-1] gestartet zu haben, konnte ihn jedoch nicht stoppen. Dies führt wahrscheinlich zu einem Speicherverlust
Dies liegt daran, dass Sie, wenn das Projekt gestoppt wird, Quarz jedoch nicht gestoppt wird, auf Ereignisse warten können, um alle geplanten Quarzaufgaben zu stoppen

import org.apache.commons.lang3.StringUtils;
import org.quartz.JobDataMap;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.HashMap;
import java.util.List;

public class MyContextListener implements ServletContextListener {
    
    
    private QuartzManager quartzManager;
    private WebApplicationContext webApplicationContext;

    public void setQuartzManager(QuartzManager quartzManager) {
    
    
        this.quartzManager = quartzManager;
    }

    /**
     * 项目初始化
     *
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
    
    
      
    }

    /**
     * 项目销毁
     *
     * @param sce
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    
    
        System.out.println("销毁=======》>");
        if (webApplicationContext == null)
            webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
        quartzManager = (QuartzManager) webApplicationContext.getBean("quartzManager");
        quartzManager.shutdownJobs();
        try {
    
    
            Thread.sleep(1000);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

Fügen Sie die Überwachung zur Datei web.xml hinzu

<listener>
	<!-- 注意修改类路径 -->
	<listener-class>*.*.*MyContextListener</listener-class>
</listener>

Guess you like

Origin blog.csdn.net/qq_41995299/article/details/114522299