• spring学习笔记(26)spring整合Quartz2持久化稳健任务调度


    《Quartz任务调度(3)存储与持久化操作配置具体解析 》一文中,我们通过配置quartz.properties属性文件实现了Quartz的数据库持久化操作。如今整合spring的原理,就是相当于把我们在属性文件里的配置属性整合进SchedulerFactoryBean中。来生成我们的Scheduler类。
    这里须要特别注意的是。我们通过Bean配置生成的JobDetail和CronTrigger或SimpleTrigger不能被序列化,因而不能持久化到数据库中,假设想要使用持久化任务调度,我们须要编程式创建Quartz的Job等相关实现类

    以下是我们的配置实例:

    spring容器配置

    <bean id="quartzDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >  
       <property name="driverClassName" value="com.mysql.jdbc.Driver"/>    
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/quartz"/>    
        <property name="username" value="root"/>    
        <property name="password" value="root"/>     
    </bean>  
    
    <!-- quartz持久化存储  -->   
    <bean name="quartzScheduler"  
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
        <property name="dataSource">  
            <ref bean="quartzDataSource" />  
        </property>  
        <property name="applicationContextSchedulerContextKey" value="applicationContext" />  
        <property name="quartzProperties">  
        <props>  
            <!-- JobStore 配置 -->  
            <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>  
               <!-- 数据表设置 -->  
            <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>  
            <prop key="org.quartz.jobStore.dataSource">myDatadource</prop>  
        </props>         
        </property>  
    </bean>    

    在连接数据前,我们须要先在数据库中创建好相应的表格,在我開始提到的文章内有相关的sql语句。此外。关于quartzProperties还有非常多配置属性,如配置线程池、集群等。在我开头提到的那篇文章内都有具体说明。

    測试类配置

    package tool.job;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    import org.quartz.Job;
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.quartz.JobKey;
    import org.quartz.ObjectAlreadyExistsException;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.SimpleTrigger;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.TriggerKey;
    import org.quartz.impl.StdSchedulerFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class pickNewsJob implements Job {
    
        @Override
        public void execute(JobExecutionContext jec) throws JobExecutionException {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
            System.out.println("在" + sdf.format(new Date()) + "更新日志");
        }
    
        public static void main(String args[]) throws SchedulerException {
            JobDetail jobDetail = JobBuilder.newJob(pickNewsJob.class)
                    .withIdentity("job1", "jgroup1").build();
            SimpleTrigger simpleTrigger = TriggerBuilder
                    .newTrigger()
                    .withIdentity("trigger1")
                    .withSchedule(
                            SimpleScheduleBuilder
                                    .repeatSecondlyForTotalCount(10, 2)).startNow()
                    .build();
            try{
                ApplicationContext ac = new ClassPathXmlApplicationContext("spring/spring-task.xml");
                Scheduler scheduler = (Scheduler) ac.getBean("quartzScheduler");
                scheduler.scheduleJob(jobDetail, simpleTrigger);
                scheduler.start();  
            }catch ( ObjectAlreadyExistsException e) {
                resumeJob();
            }
        }
        /**
         *依据数据库中的记录 恢复异常中断的任务
         */
        public static void resumeJob() throws SchedulerException {
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            Scheduler scheduler = schedulerFactory.getScheduler();
            // ①获取调度器中全部的触发器组
            List<String> triggerGroups = scheduler.getTriggerGroupNames();
            // ②又一次恢复在tgroup1组中,名为trigger1触发器的执行
            for (int i = 0; i < triggerGroups.size(); i++) {
                List<String> triggers = scheduler.getTriggerGroupNames();
                for (int j = 0; j < triggers.size(); j++) {
                    Trigger tg = scheduler.getTrigger(new TriggerKey(triggers
                            .get(j), triggerGroups.get(i)));
                    // ②-1:依据名称推断
                    if (tg instanceof SimpleTrigger
                            && tg.getDescription().equals("jgroup1.DEFAULT")) {//因为我们之前測试没有设置触发器所在组,所以默觉得DEFAULT
                        // ②-1:恢复执行
                        scheduler.resumeJob(new JobKey(triggers.get(j),
                                triggerGroups.get(i)));
                    }
                }
            }
            scheduler.start();
    
        }
    }

    在这里,假设我们測试时在执行中断后再反复执行。会出现ObjectAlreadyExistsException异常。原因是我们创建的JobDetail和Trigger等的名字和数据库中已有记录冲突。新的任务尝试持久到数据库失败。在程序中。我的处理方法是先捕捉异常,然后调用恢复任务方法,来又一次执行异常中断的任务。

    源代码下载

    本例源代码可到我的github仓库https://github.com/jeanhao/spring的springQuartz目录下载

  • 相关阅读:
    利用Node.js的Net模块实现一个命令行多人聊天室
    JS判断鼠标进入容器方向的方法和分析window.open新窗口被拦截的问题
    Node.js:进程、子进程与cluster多核处理模块
    Node.js:理解stream
    Node.js:Buffer浅谈
    Node.js:OS模块
    一个unsigned int 数的二进制表示中有多少个1
    一个栈的入栈序列为ABCDEF,则不可能的出栈序列是
    文件操作:获取一个文件行数的方法
    利用sourceinsight宏(Quicker.em)提高编码效率和质量
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7219286.html
Copyright © 2020-2023  润新知