Spring4.0.6 +Quartz 2.2.1动态添加、修改、删除、关闭定时任务(可结合数据库以及空指针异常问题的解决)

不懂定时器的可以阅读这位作者的文章:Quartz 2.2 的实现原理和运行过程http://blog.csdn.net/xlxxcc/article/details/52104463

spring配置

<!-- 定时器 -->
	<!-- 这个类用来做需要完成的业务-->
	<bean id="initalJob" class="com.shanreal.scheduler.IntialQuartzJob"></bean>

	<!-- 定时任务 -->
	<!-- 定义调用对象和调用对象的方法,这个配置和普通的一样的,id是JobDetail的名字  -->
	<bean id="jobtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<!-- 调用的类  -->
		<property name="targetObject" ref="initalJob"/>
		<!-- 调用类中的方法  -->
		<property name="targetMethod" value="initial" />
		<!-- 是否并发  -->
		<property name ="concurrent" value ="false"  />
	</bean>

	<!-- 定义触发时间 ,这边就不同了,这里必须将时间设置成无限长,因为我们要去读取数据库的时间来做为定时器的触发时间-->
	<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean ">
		<property name="jobDetail" ref="jobtask" />
		<!-- cron表达式  -->
		<property name="cronExpression" value="0 0/2 * * * ?" />
	</bean>

	<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序  -->
	<bean id="startQuertz" lazy-init="true" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="jobFactory" ref="jobFactory" />
		<property name="triggers">
			<list>
				<ref bean="cronTrigger" />
			</list>
		</property>
	</bean>

	<!--这个类是用来设置触发时间的, startJobs方法启动调度容器,然后按照上面触发器每隔1s执行所配置的myJob2.doSomething()方法 -->
	<bean id="quartzManager" class="com.shanreal.scheduler.QuartzManager" lazy-init="false" init-method="startJobs" >
		<!--这个对象一定要注入,这样类才能进行管理,还有在类型要用get set方法,不然会报错。-->
		<property name="scheduler" ref="startQuertz" />
	</bean>

QuartzManager.java 动态添加、修改和删除定时任务管理类

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;

    /**
     * @Description: 添加一个定时任务
     *
     * @param jobName 任务名
     * @param jobGroupName  任务组名
     * @param triggerName 触发器名
     * @param triggerGroupName 触发器组名
     * @param jobClass  任务
     * @param cron   时间设置,参考quartz说明文档
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void addJob(String jobName, String jobGroupName,
                       String triggerName, String triggerGroupName, Class jobClass, String cron) {
        try {
            // 任务名,任务组,任务执行类
            JobDetail jobDetail= JobBuilder.newJob(jobClass).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();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description: 修改一个任务的触发时间
     *
     * @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)) {
                /** 方式一 :调用 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 = scheduler.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class<? extends Job> jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先删除,然后在创建一个新的Job */
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description: 移除一个任务
     *
     * @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);
        }
    }

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

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

    public Scheduler getScheduler() {
        return scheduler;
    }

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

}

IntialQuartzJob:初始化定时器

@Component
public class IntialQuartzJob {

    public void initial(){
        System.out.println("----------初始化定时器操作---------");
        //这里可以写初始执行的定时器方法
    }
}

JobFactory:用于处理异常(一定要有这个,不然自定义的异常直接被job处理会造成程序报空指针异常)

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.Service;

@Service("jobFactory")
public class JobFactory extends AdaptableJobFactory {

    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle)
            throws Exception {
        Object jobInstance = super.createJobInstance(bundle);
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }

}

IntialOtherQuartzJob:系统启动时初始化添加定时器(可以从数据库读取数据)

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class IntialOtherQuartzJob implements InitializingBean {

    @Autowired
    private QuartzManager quartzManager;

     public void initialMethod() throws Exception {
        System.out.println("--------bean:配置:初始化数据库存储的定时器配置--------");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("--------接口实现:初始化数据库存储的定时器配置--------");
        quartzManager.addJob("班次下线","test","test","test",ClassesQuartzJob.class,"0 0 0/8 * * ?");
    }

关于系统启动时初始化执行方法:https://blog.csdn.net/honghailiang888/article/details/73333821

手动测试:

public class Test {

    public static String JOB_NAME = "动态任务调度";  
    public static String TRIGGER_NAME = "动态任务触发器";  
    public static String JOB_GROUP_NAME = "XLXXCC_JOB_GROUP";  
    public static String TRIGGER_GROUP_NAME = "XLXXCC_JOB_GROUP"; 

    public static void main(String[] args) {
        try {  
            System.out.println("【系统启动】开始(每1秒输出一次)...");    
            QuartzManager.addJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME, MyJob.class, "0/1 * * * * ?");    

            Thread.sleep(5000);    
            System.out.println("【修改时间】开始(每5秒输出一次)...");    
            QuartzManager.modifyJobTime(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME, "0/5 * * * * ?");    

            Thread.sleep(6000);    
            System.out.println("【移除定时】开始...");    
            QuartzManager.removeJob(JOB_NAME, JOB_GROUP_NAME, TRIGGER_NAME, TRIGGER_GROUP_NAME);    
            System.out.println("【移除定时】成功");    
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }
}

个人的数据库和页面没有实现,由于保密原因,以后有机会再自己造数据添加吧。

这里有个比较全面的,数据库+页面:https://blog.csdn.net/qq_21454973/article/details/81979660

猜你喜欢

转载自blog.csdn.net/wind_cp/article/details/84614376