• Quartz框架


    quartz(开源项目)

    Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.3.2。

    1.1. Quartz开发步骤说明

    1)创建任务 - Job     你要干什么?

    2)创建触发器-Trigger  要什么时候做?

    3)创建任务调度-Scheduler  什么时候干什么?

    1.2. 创建Quartz的Java应用

    1.2.1.   导入quartz的坐标

     <dependencies>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-jobs</artifactId>
                <version>2.3.2</version>
            </dependency>
        </dependencies>

    1.2.2.   定义Job对象

    /**
     * 自定义Job
     * @author lenovo
     *
     */
    public class TestJob implements Job{
    
        //execute:一旦任务触发,就会执行此方法
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("任务被触发:"+sdf.format(new Date()));
        }
    
    }

    1.2.3.   编写任务调用测试类

    Quartz分内简单触发器和日历触发:

    简单触发器(SimpleTrigger):主要完成固定重复地任务(按照秒,分,小时)来重复。(例如,每隔30分钟做事件)

    日历触发器(CronTrigger): 主要可以按照日历的形式进行重复地任务。(例如:每个星期的一,三,五晚上12点做事情)(常用)

    1.2.3.1.       编写简单触发器版本

    /**
     * 简单触发器案例
     * @author lenovo
     *
     */
    public class SimpleTriggerDemo {
    
        
        public static void main(String[] args) throws Exception {
            //1)创建任务 - Job     你要干什么?
            JobDetail job = JobBuilder
                        .newJob(TestJob.class)
                        .build();
            
            //2)创建触发器-Trigger  要什么时候做?
            Trigger trigger = TriggerBuilder
                                .newTrigger()
                                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(3))
                                .build();
            //3)创建任务调度-Scheduler  什么时候干什么?
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //建立job和trigger的关系
            scheduler.scheduleJob(job, trigger);
            
            //4)启动任务
            scheduler.start();
        }
        
    }

    1.3. 创建CronTrgger日历触发器(比较常用)

    按照日历规则进行重复。例如 每个1,3,5进行重复。

    /**
     * 日历触发器案例
     *
     */
    public class CronTriggerDemo {
        
        public static void main(String[] args) throws Exception {
            //1)创建任务 - Job     你要干什么?
            JobDetail job = JobBuilder
                        .newJob(TestJob.class)
                        .build();
            
            //2)创建触发器-Trigger  要什么时候做?
            Trigger trigger = TriggerBuilder
                                .newTrigger()
                                //传入cron表达式(日历表达式)
                                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"))
                                .build();
            //3)创建任务调度-Scheduler  什么时候干什么?
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //建立job和trigger的关系
            scheduler.scheduleJob(job, trigger);
            
            //4)启动任务
            scheduler.start();
        }
        
    }

    1.4. cron表达式的语法

    CronScheduleBuilder.cronSchedule("0/5 * * * * ? *")

     

    2.   Spring整合Quartz框架

    2.1. 导入quartz和spring的坐标

    quartz的坐标:

    <!-- quartz任务调度 -->
    <dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
    </dependency>
    <dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.3.2</version>
    </dependency>

    spring的坐标:

    spring整合quartz的API的spring-context-support

    <!-- spring-context-support -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
            </dependency>

    2.2. 编写Job任务类

    /**
     * 自定义Job
     * @author lenovo
     *
     */
    public class TestJob implements Job{
    
        //execute:一旦任务触发,就会执行此方法
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("任务被触发:"+sdf.format(new Date()));
        }
    
    }

    2.3. 编写applicationContext-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.xsd">
        
        <!-- Spring整合Quartz -->
        <!-- 1.创建JobDetail -->
        <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
            <!-- 关联我们的Job类 -->
            <property name="jobClass" value="com.fyc.bos.jobs.TestJob"/>
        </bean>
    
        <!-- 2.创建Trigger:SimpleTriiger -->
        <bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
            <!-- 关联JobDetail -->
            <property name="jobDetail" ref="jobDetail"/>
            <!-- 间隔时间 (毫秒)-->
            <property name="repeatInterval" value="3000"></property>
            <!-- 重复次数 -->
            <property name="repeatCount" value="4"></property>
        </bean>
        
        
        <!-- 3.创建Scheduler -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <!-- 关联trigger -->
            <property name="triggers">
                <list>
                    <ref bean="trigger"/>
                </list>
            </property>
        </bean>    
        
    </beans>

    导入xml:

    <import resource="classpath:applicationContext-quartz.xml"/>

    2.4. CronTrigger配置

    <?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.xsd">
        
        <!-- Spring整合Quartz -->
        <!-- 1.创建JobDetail -->
        <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
            <!-- 关联我们的Job类 -->
            <property name="jobClass" value="com.fyc.bos.jobs.TestJob"/>
        </bean>
    
        <!-- 2.创建Trigger:SimpleTriiger -->
        <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <!-- 关联JobDetail -->
            <property name="jobDetail" ref="jobDetail"/>
            <!-- cron表达式 -->
            <property name="cronExpression" value="0/5 * * * * ? *"/>
        </bean>
        
        
        <!-- 3.创建Scheduler -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <!-- 关联trigger -->
            <property name="triggers">
                <list>
                    <ref bean="trigger"/>
                </list>
            </property>
        </bean>    
        
    </beans>

     我的实际项目中的使用

    导入的maven依赖

     <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz-jobs</artifactId>
                <version>2.3.2</version>
            </dependency>
    //其它的依赖略

    要触发的实际执行的类

    这里是根据现在的时间和数据库的实际比较进行的跟新操作。后面的逻辑代码就不贴出了。

    public class PromotionJob implements Job {
            @Resource
            private PromotionService promotionService;
    
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            //结束时间是否小于系统时间,如果是的话,自动更新status,改为0。
            //System.out.println("PromotionJob任务被触发...");
            promotionService.updateStatus(new Date());
        }
    }

    配置信息

    applicationContext-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.xsd">
    
    
        <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
            <!-- 关联我们的Job类 -->
            <property name="jobClass" value="com.fyc.bos.jobs.PromotionJob"/>
            <!-- 2.创建Trigger:SimpleTriiger -->
        </bean>
      
        <!-- 2.创建Trigger:SimpleTriiger -->
        <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <!-- 关联JobDetail -->
            <property name="jobDetail" ref="jobDetail"/>
            <!-- cron表达式 5秒测试一次-->
            <property name="cronExpression" value="0/5 * * * * ? *"/>
        </bean>
    
        <!-- 3.创建Scheduler -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <!-- 覆盖setJobFactory ,使用我们自定义的JobFactory-->
            <property name="jobFactory" ref="jobFactory"/>
            <!-- 关联trigger -->
            <property name="triggers">
                <list>
                    <ref bean="trigger"/>
                </list>
            </property>
        </bean>
    
    </beans>

    记得把这份配置导入到spring的主配置中

    <import resource="applicationContext-quartz.xml"/>

    上面的配置我由于是先测试使用了每五秒做为一次更新。这个日历更新的频率要根据你实际的项目需求去修改

    上面的<property name="jobFactory" ref="jobFactory"/>没有添加这个自己注入到的spring对象会出现无法注入PromotionService对象。

    在Job对象无法注入Spring对象的问题

    原因:Spring框架整合了quartz整合,在创建JobDetail对象的过程中,使用AdapterJobFactory的createJobInstance这个方法去创建JobDetail对象的:

     

    通过查看源码,我们发现Spring在创建JobDetail只是用了反射代码直接创建了对象,而没有把该对象放入Spring的IOC容器管理,所以无法在该对象中注入其他Spring对象。

    解决办法:手动把JobDetail对象放入SpringIOC容器中。

    设计一个JobFactory:

    /*
     * 自定义JobFactory对象,重写createJobInstance方法
     */
    @Component
    public class MyJobFactory extends AdaptableJobFactory {
    
        @Resource
        private AutowireCapableBeanFactory factory;
        
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            //调用父类的原有的方法创建JobDetail对象
            Object jobDetail = super.createJobInstance(bundle);
            //把JobDetail放入SpringIOC容器中管理
            factory.autowireBean(jobDetail);
            return jobDetail;
        }
    }



  • 相关阅读:
    Git 游离态的一次问题解决
    idea每次新建项目的默认路径
    springboot 整合 freemarker
    Linux 学习网站
    springtask 基本使用和 cron 表达式
    volatile 关键字 和 i++ 原子性
    python 自动补全
    nagios维护之常见问题
    nagios维护之添加监控
    windows下python文件与文件夹操作
  • 原文地址:https://www.cnblogs.com/fengyangcai/p/12963539.html
Copyright © 2020-2023  润新知