Quartz定时框架的使用、与spring整合的使用

**

Quartz定时框架的使用、与spring整合的使用

**

一、Quartz是什么

Quartz是一个日常任务管理系统,也可以说成是一个定时器,他可以和任何其他软件系统集成或者一起使用。Quartz 相当“轻量”,并且需要非常少的步骤/配置,如果需求比较基本,Quartz确实非常容易使用。

Quartz 具有容错性,并且可以在你系统重起的时候持久化(记住)被纳入日程的任务。

二、为什么不使用Java.util.Timer?

  1. Java 定时器没有持久化机制。
  2. Java 定时器的日程管理不够灵活(只能设置开始时间、重复的间隔,设置特定的日
    期、时间等)
  3. Java 定时器没有使用线程池(每个 Java 定时器使用一个线程)
  4. Java 定时器没有切实的管理方案,你不得不自己完成存储、组织、恢复任务的措施。

三、如何避免一个job被并发激活

使 Job 类实现 StatefulJob 接口,而不是 Job 接口。

四、Quartz介绍

1、Quartz官网http://www.quartz-scheduler.org/

2、下载目录这里写图片描述

使用时需要导入相应jar包,在下载目录里都有

3、入门案例

 import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.impl.StdSchedulerFactory;

    public class Demo1 {
        public static void main(String[] args) throws SchedulerException {
            //定时器对象
            SchedulerFactory scheduler = new StdSchedulerFactory().getScheduler();
            //开启定时器任务
            scheduler.start();
            //关闭定时器任务
            scheduler.shutdown();
        }
    }

4、Quartz的使用

    SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
    Scheduler sched = schedFact.getScheduler();
    sched.start();
    JobDetail jobDetail = new JobDetail("myJob",null,DumbJob.class);
    Trigger trigger = TriggerUtils.makeHourlyTrigger(); //每个小时激活一次
    trigger.setStartTime(TriggerUtils.getEvenHourDate(new Date()));//在下一个
    小时启动。
    trigger.setName("myTrigger");
    sched.scheduleJob(jobDetail, trigger);

五、Quartz定时框架simpleTrigger开发使用

如果需要让任务只在某个时刻执行一次,或者,在某个时刻开始,然后按照某个时间

间隔重复执行,simpleTrigger就可以满足你的需求

SimpleTrigger 有几个不同的构造函数

第一种

 public SimpleTrigger(String name,
                        String group,
                        Date startTime,
                        Date endTime,
                        int repeatCount,
                        long repeatInterval)

SimpleTrigger Example 1 – 从现在 10 秒钟后开始触发,并且只触发一次。

    long startTime = System.currentTimeMillis() + 10000L;
    SimpleTrigger trigger = new SimpleTrigger("myTrigger",
                                                null,
                                                new Date(startTime),
                                                null,
                                                0,
                                                0L);

SimpleTrigger Example 2 – 创建一个立即触发的触发器,并且每隔 60 秒钟触发一

次,直到永远。

 SimpleTrigger trigger = new SimpleTrigger("myTrigger",
                                                null,
                                                new Date(),
                                                null,
                                                SimpleTrigger.REPEAT_INDEFINITELY,
                                                60L * 1000L);

SimpleTrigger Example 3 - 创建一个立即触发的触发器,并且每隔 10 秒重复一次,

直到 40 秒钟以后。

 long endTime = System.currentTimeMillis() + 40000L;
    SimpleTrigger trigger = new SimpleTrigger("myTrigger",
                                                "myGroup",
                                                new Date(),
                                                new Date(endTime),
                                                SimpleTrigger.REPEAT_INDEFINITELY,
                                                10L * 1000L);

SimpleTrigger Example 4 - 创建一个触发器,开始触发时间为 2018 年 3 月 17 上

午 午 10 :30 分,并且重复 5 次。(总共触发 6 次)每次延迟 30 秒钟。

 java.util.Calendar cal = new java.util.GregorianCalendar(2018, cal.MARCH, 17);
                        cal.set(cal.HOUR, 10);
                        cal.set(cal.MINUTE, 30);
                        cal.set(cal.SECOND, 0);
                        cal.set(cal.MILLISECOND, 0);
                        Data startTime = cal.getTime()
    SimpleTrigger trigger = new SimpleTrigger("myTrigger",
                                                null,
                                                startTime,
                                                null,
                                                5,
                                                30L * 1000L);

当然还有另一种

1、重要接口说明

1)Job:工作任务,你要做什么,Job一般自定义实现,由接口JobDetail来创建

2)Trigger执行工作任务,什么时间执行,多久执行一次常用的有:SimpleTrigger、CronTrigger

2)Scheduler定时器对象,开启定时任务

2、编写工作任务

 import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class HelloJob implements Job {

        private Logger logger = LoggerFactory.getLogger(this.getClass());

        public void execute(JobExecutionContext context) throws JobExecutionException {
            logger.info("hello,quartz!");
        }

    }

3、编写定时任务代码

    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;

    public class Demo2 {
        public static void main(String[] args) throws SchedulerException {
            //定时器对象
            SchedulerFactory scheduler = new StdSchedulerFactory().getScheduler();
            //定义一个工作对象
            JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
            //定义触发器
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();

            scheduler.scheduleJob(job, trigger);
            //开启定时任务
            scheduler.start();
        }
    }

1)对象TriggerBuilder启动任务时间

2)对象SimpleScheduleBuilder进行简单任务重复执行

3)repeatSecondly…() 多少秒后重复执行

4)repeatMinutely…() 多少分钟后重复执行

5)repeatHourly…() 多少小时后重复执行

六、quartz定时框架CronTrigger开发使用

    import org.quartz.CronScheduleBuilder;
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.SchedulerFactory;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.quartz.impl.StdSchedulerFactory;

    import cn.itcast.quartz.demo2.HelloJob;

    public class Demo5 {
        public static void main(String[] args) throws SchedulerException {
            SchedulerFactory sf = new StdSchedulerFactory();
            Scheduler scheduler = sf.getScheduler();

            JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

            Trigger trigger = TriggerBuilder.newTrigger().forJob("job1", "group1").startNow()
                    .withSchedule(CronScheduleBuilder.cronSchedule("0 1 23 ? * SUN")).build();

            scheduler.scheduleJob(job, trigger);

            scheduler.start();
        }
    }

1)Cron表达式取值

字段名 允许的值 允许的特殊字符

秒 0-59 , - * /

分 0-59 , - * /

小时 0-23 , - * /

日 1-31 , - * ? / L W C

月 1-12 or JAN-DEC , - * /

周几 1-7 or SUN-SAT , - * ? / L C #

年 (可选字段) empty, 1970-2099 , - * /

2)具体说明

Day-of-month 和 Day-of-week必须有一个指定为?

“?”字符:表示不确定的值

“,”字符:指定数个值

“-”字符:指定一个值的范围

 “/”字符:指定一个值的增加幅度。n/m表示从n开始,每次增加m

“L”字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期X

6L表示该月最后一个星期五

“W”字符:指定离给定日期最近的工作日(周一到周五)

“#”字符:表示该月第几个周X。6#3表示该月第3个周五

字符“W”只允许日期域出现。这个字符用于指定日期的最近工作日。例如:如果你在日期域中写 “15W”,表示:这个月15号最近的工作日。所以,如果15号是周六,则任务会在14号触发。如果15好是周日,则任务会在周一也就是16号触发。如果是在日期域填写“1W”即使1号是周六,那么任务也只会在下周一,也就是3号触发,“W”字符指定的最近工作日是不能够跨月份的。字符“W”只能配合一个单独的数值使用,不能够是一个数字段,如:1-15W是错误的。

“L”和“W”可以在日期域中联合使用,LW表示这个月最后一周的工作日。

字符“#”只允许在星期域中出现。这个字符用于指定本月的某某天。例如:“6#3”表示本月第三周的星期五(6表示星期五,3表示第三周)。“2#1”表示本月第一周的星期一。“4#5”表示第五周的星期三。

字符“C”允许在日期域和星期域出现。这个字符依靠一个指定的“日历”。

它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。

3)举例:

每隔5秒执行一次:*/5 * * * * ?

每隔1分钟执行一次:0 */1 * * * ?

每天23点执行一次:0 0 23 * * ?

每天凌晨1点执行一次:0 0 1 * * ?

每月1号凌晨1点执行一次:0 0 1 1 * ?

每月最后一天23点执行一次:0 0 23 L * ?

在26分、29分、33分执行一次:0 26,29,33 * * * ?

每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?

每天中午12点触发 0 0 12 * * ?

每天上午10:15触发 0 15 10 ? * *

每天上午10:15触发 0 15 10 * * ?

每天上午10:15触发 0 15 10 * * ? *

2018年的每天上午10:15触发 0 15 10 * * ? 2018

在每天下午2点到下午2:59期间的每1分钟触发 0 * 14 * * ?

在每天下午2点到下午2:55期间的每5分钟触发 0 0/5 14 * * ?

在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 0 0/5 14,18 * * ?

在每天下午2点到下午2:05期间的每1分钟触发 0 0-5 14 * * ?

每年三月的星期三的下午2:10和2:44触发 0 10,44 14 ? 3 WED

周一至周五的上午10:15触发 0 15 10 ? * MON-FRI

每月15日上午10:15触发 0 15 10 15 * ?

每月最后一日的上午10:15触发 0 15 10 L * ?

每月的最后一个星期五上午10:15触发 0 15 10 ? * 6L

2015年至2018年的每月的最后一个星期五上午10:15触发 0 15 10 ? * 6L 2015-2018

每月的第三个星期五上午10:15触发 0 15 10 ? * 6#3

七、quartz定时框架和spring集成使用

1、建立war包maven项目,导入坐标

 <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz-jobs</artifactId>
        <version>2.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>4.1.7.RELEASE</version>
    </dependency>

2、配置web.xml

    <!-- spring配置文件位置 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </context-param>
        <!-- spring核心监听器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

3、配置applicationContext.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" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd ">

        <context:component-scan base-package="cn.itcast" />

        <bean id="helloJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">  
            <property name="jobClass" value="cn.itcast.job.HelloJob"/>  
            <property name="jobDataAsMap">  
                 <map>  
                    <entry key="timeout" value="5"/>
                 </map>  
            </property>  
        </bean> 

        <!-- ======================== 调度触发器 ======================== -->
        <bean id="cronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
            <property name="jobDetail" ref="helloJob"></property>
            <property name="cronExpression" value="0 54 * * * ?"></property>
        </bean>

        <!-- ======================== 调度工厂 ======================== -->
        <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
            <property name="jobFactory" ref="jobFactory" />
            <property name="triggers">
                <list>
                    <ref bean="cronTriggerBean" />
                </list>
            </property>
        </bean>

    </beans>

4、代码编写

HelloService

 import org.springframework.stereotype.Service;

    @Service
    public class HelloService {
        public void sayHello() {
            System.out.println("hello,quartz service !");
        }
    }

helloJob

 import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.QuartzJobBean;

    import cn.itcast.service.HelloService;

    public class HelloJob extends QuartzJobBean {

        @Autowired
        private HelloService helloService;

        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            helloService.sayHello();
        }

    }

JobFactory

 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;
        }

    }

八、quartz和spring整合Bean无法注入问题

需要在Scheduler中自定义JobFactory

AutowireCapableBeanFactory这个接口一般在applicationContext的内部是较少使用的,它的功能主要是为了装配applicationContext管理之外的Bean

上面代码已经解决了这个问题

猜你喜欢

转载自blog.csdn.net/roc_wl/article/details/82085209