首页 > 编程语言 > 详细

spring 整合 quertz 并实现定时器页面动态配置功能,支持脚本参数配置

时间:2019-03-18 10:11:02      阅读:183      评论:0      收藏:0      [点我收藏+]

背景

  • Java定时任务的实现技术主流的有三种,Java自带的Java.util.Time类、Quartz、Spring3.0以后自带的task。下面我们使用的是Quartz。
  • 项目中如果需要一个定时任务,我们首先需要开发一个job,然后在xml中配置,接着发布使用。考虑以下几个问题:
  1. 如果发布后这个定时任务的时间需要改变一下怎么办
  2. 这个定时任务需要参数,但是现在参数发生了改变怎么办
  3. 一个逻辑可以启动好几个定时任务,只是参数和时间不一样,那么我们是不是要在xml中复用同一个job,配置多个定时任务呢。
  • 根据以上问题,我们可以考虑实现定时器的时间和参数动态配置,保存在数据库中,项目启动时去数据库加载数据,初始化定时任务。当参数发生改变,我们使用调度器改变任务参数。这样我们就可以实现脚本的灵活复用、脚本时间动态配置和定时任务参数的动态配置
  • 以下配置基于maven和spring mvc

步骤

1、在POM文件中加入依赖

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>

2、配置quartz.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-3.1.xsd">

<bean id="startQuertz" lazy-init="true" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    </bean>
    <bean id="quartzManager" class="com.hello.quartz.QuartzManager" lazy-init="false" init-method="startJobs" >
        <property name="scheduler" ref="startQuertz" />
    </bean>
</beans>

3、在applicationContext.xml 加入quartz的依赖

<import resource="quartz.xml" />

4、创建任务调度器QuartzManager

package com.cnc.ci.cs.quartz;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;

public class QuartzManager {

    private Scheduler scheduler;

    public Scheduler getScheduler() {
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    /**
     * 功能: 添加一个定时任务
     * @param jobName 任务名,可以是JOB class文件的首字母小写
     * @param jobGroupName  任务组名
     * @param triggerName 触发器名,在job执行时JobExecutionContext参数中可以获取到值,((CronTriggerImpl) ((JobExecutionContextImpl) jobExecutionContext).getTrigger()).getName()
     * @param triggerGroupName 触发器组名
     * @param jobClass  任务的类类型  TestJob.class
     * @param cron   时间设置 表达式
     */
    public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String cron,
            Object... objects) {
        try {
            //校验触发器是否已经存在,如果存在,不再创建。注意,每个触发器的triggerName应该不一样
            if (scheduler.checkExists(TriggerKey.triggerKey(triggerName, triggerGroupName))) {
                return;
            }
            // 任务名,任务组,任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            // 触发器
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    //该数据可以通过Job中的JobDataMap dataMap = context.getJobDetail().getJobDataMap();来进行参数传递值
                    jobDetail.getJobDataMap().put("data" + (i + 1), objects[i]);
                }
            }
            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();
            }*/

        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 功能:修改一个任务的触发时间
     * @param jobName
     * @param jobGroupName
     * @param triggerName 触发器名
     * @param triggerGroupName 触发器组名
     * @param cron   时间设置,参考quartz说明文档
     */
    public void modifyJobTime(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String cron) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                // 触发器
                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);
            }
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 功能: 移除一个任务
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     */
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

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

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

 

5、初始化定时任务

      通过ApplicationListener接口监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener<ContextRefreshedEvent>接口可以收到监听动作,并执行程序

 

package com.cnc.ci.cs.quartz;

import com.cnc.ci.cs.timerjob.TestJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import com.cnc.portal.spring.SpringContextHolder;

@Component
public class ModJobManager implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ModJobManager.class);

    public void init() {
        LOGGER.info("初始化job!");
        //通过spring上下文获取quartzManager,SpringContextHolder 类见下一个文件
        QuartzManager quartzManager = (QuartzManager) SpringContextHolder.getBean("quartzManager");
        quartzManager.addJob("testJob", "testJob", "testJob1", "testJob1", TestJob.class, "0 0/2 * * * ?");
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        init();
    }

}
package com.hello.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextHolder implements ApplicationContextAware {

    // Spring应用上下文环境
    public static ApplicationContext applicationContext;

    /**
     * 实现ApplicationContextAware接口的回调方法。设置上下文环境
     *
     * @param applicationContext
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtil.applicationContext = applicationContext;
    }

    /**
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }

}

 

6、测试JOB

package com.cnc.ci.cs.timerjob;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.impl.JobExecutionContextImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class TestJob implements Job {
    private static final Logger LOGGER = LoggerFactory.getLogger(EmailSendJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //获取trigger名字,trigger 名字+group 是触发器的唯一标识
        LOGGER.info(((CronTriggerImpl) ((JobExecutionContextImpl) jobExecutionContext).getTrigger()).getName());
        //获取触发器的时间
        LOGGER.info(((CronTriggerImpl) ((JobExecutionContextImpl) jobExecutionContext).getTrigger()).getCronExpression());
        //业务逻辑
    }
}

 

spring 整合 quertz 并实现定时器页面动态配置功能,支持脚本参数配置

原文:https://www.cnblogs.com/blackl/p/10538792.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!