Spring整合Quartz

定时任务两种方式,Spring很好的封装使用Quartz的细节,第一种方式是利用SPring封装的Quartz类进行特定方法的实现,第二种是通过透明的使用Quartz达到定时任务开发的目的,总体说第二种对开发人员更方便!

配置Spring的任务调度抽象层简化了任务调度,在Quartz的基础上提供了更好的调度对象。Spring使用Quartz框架来完成任务调度,创建Quartz的作业Bean(JobDetail)

Quartz编码思路
1)编写Job(任务) -   你想做什么?
2)编码Trigger(触发器) - 你想什么时候做?
3)编码Scheduler(任务调度): 你想什么时候做什么?

使用Java程序演示Quartz

1.导入quartz坐标

<!-- quartz任务调度 -->
<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>

2.定义一个Job(任务)

/**
 *  该类须实现Job接口并重写execute方法
 *  execute:任务触发就调用此方法
 */
public class MyJob implements Job{

    @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()));
    }
}

3.编写代码创建任务调度

在Quartz分为两种触发器:
1)简单触发器(SimpleTrigger):简单地按照秒,分,小时重复。
       例如:每5分钟来触发一次任务
2)日历触发器(CronTrigger):按照日历规则进行触发。(比较常用)
       例如:每个星期2,4,5凌晨2点触发任务。
1).简单触发器例子
public class Demo1 {

    public static void main(String[] args) throws Exception {
        //1.创建Job任务
        JobDetail job = JobBuilder.newJob(MyJob.class).build();

        //2.创建Trigger触发器,这里使用的SimpleTrigger类
        //repeatSecondlyForever: 按照秒重复,每秒重复一次
        Trigger trigger = TriggerBuilder.newTrigger().withSchedule(
                    SimpleScheduleBuilder.repeatSecondlyForever()
                    ).build();

        //3.创建任务调度对象
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        //关联Job和trigger
        scheduler.scheduleJob(job, trigger);

        //启动任务
        scheduler.start();
    }
}
2).日历触发器
public class Demo2 {

    public static void main(String[] args) throws Exception {
        //1.创建Job任务
        JobDetail job = JobBuilder.newJob(MyJob.class).build();

        //2.创建Trigger触发器
        //withSchedule:指定触发器
        Trigger trigger = TriggerBuilder.newTrigger().withSchedule(
                    //cronSchedule:指定日历规则字符串
                    CronScheduleBuilder.cronSchedule("0/3 * * * * ? *")
                    ).build();

        //3.创建任务调度对象
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        //关联Job和trigger
        scheduler.scheduleJob(job, trigger);

        //启动任务
        scheduler.start();
        //scheduler.shutdown();结束任务
    }
}

Quartz有两大触发器,除了上面的Simpletrigger外,还有CronTrigger。CronTrigger能够提供对复杂的触发器表达式的支持。CronTrigger时基于Unix Cron守护进程的,它是一个调度程序,支持简单而强大的触发器语法。

使用Cron Trigger主要的是掌握Cron表达式。Cron表达式包含6个必要组件和1个可选组件,如下表所示。

CronTrigger组件

位置含义允许的特殊字符
1秒(0-59), - * /
2分(0-59), - * /
3小时(0-24), - * /
4日期(1-31), - * / ? L W C
5月(JAN-DEC或1-12), - * /
6星期(SUN-SAT或1-7), - * / ? L C #
7年(可选,1970-2099),若为空,表示全部时间范围, - * /

特殊字符含义

特殊字符说明
*通配符,任意值
?无特定值。通常和其他指定的值一起使用,表示必须显示该值但不能检查
-范围。e.g.小时域中10-12表示10:00,11:00,12:00
,列分隔符。可以让你指定一系列的值。e.g.在星期域中指定MON,TUE和WED
/增量。表示一个值的增量。e.g.分钟域中0/1表示从0开始,每次增加1min
L表示Last。它在日期域和星期域中表示有所不同。在日期域中,表示这个月的最后一天,而在星期域中永远是7(即星期六)。当你希望使用星期域中的某一天时,L字符非常有用。e.g.星期域中6L表示每个月的最后一个星期五
W在本月内里当天最近的工作日出发,所谓的最近工作日,即当天到工作日的前后最短距离,如果当天即为工作日,则距离为0;所谓本月内是指不能跨月渠道最近工作日,即使前/后月份的最后一天或者第一天满足最近工作日的条件。e.g.LW表示这个月的追后一个工作日触发,W强烈依赖于月份
#表示该月的第几个星期,e.g.1#2表示每个月第一个星期的星期一
C日历值。日历值时更具一个给定的日历计算出来的。在日历值域中给定一个20C将在20日(日历包括20日)或20日后日历中包含的第一天(不包括20日)激活触发器。e.g.在星期域中使用6C表示日历中星期五(日历包括星期五)或者第一天(日历不包括星期五)

Cron表达式举例:

“30 * * * * ?”每半分钟触发任务

“30 10 * * * ?"每小时的10分30秒触发任务

”30 10 1 * * ?“每天的1点10分30秒触发任务

”30 10 1 20 * ?“每月20号的1点10分30秒触发任务

”30 10 1 20 10 ? *“每年的10月20号的1点10分30秒触发任务

”30 10 1 30 10 ? 2011“2011年的10月20号1点10分30秒触发任务

”30 10 1 ? 10 * 2011“2011年的10月每天1点10分30秒触发任务

”30 10  1 ? 10 SUN 2011“2011年的10月的每个星期天的1点10分30秒触发任务

”15,30,45 * * * * ?“每15秒,30秒,45秒触发任务

”15-45 * * * *?“在15到45秒内,每秒都触发任务

”15/5 * * * *?“每分钟的15秒开始触发,每隔5秒触发一次

”15-30/5 * * * * ?“每分钟的15秒到30秒之间触发任务,每隔五秒触发一次

”0 0/3 * * * ?"每小时的0分0秒开始,每隔3分钟触发任务

“0 15 10 ? * MON-FRI"星期一到星期五的10点15分触发任务

”0 15 10 L * ?“每个月的最后一天的10点15分触发任务

”0 15 10 LW * ?"每个月的最后一个工作日的10点5分触发任务

“0 15 10 ? * 5L"每个月的最后一个星期四的10点15分触发任务

”0 15 10 ? * 5#3“每月的第3个星期的星期四的10点15分触发任务

使用Web应用Spring整合Quartz

导入quartz和spring坐标:

quartz:

<!-- quartz任务调度 -->
<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>

spring:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
</dependency>
定义一个任务
/**
 *  该类须实现Job接口并重写execute方法
 *  execute:任务触发就调用此方法
 */
public class MyJob implements Job{

    @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)编写applicationContext-quartz-simple.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.创建Job -->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- 关联自己的任务 -->
        <property name="jobClass" value="com.jobs.MyJob"/>
    </bean>

    <!-- 2.创建Trigger -->
    <bean id="trigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <!-- 关联JobDetail -->
        <property name="jobDetail" ref="jobDetail"/>
        <!-- 简单地重复( 单位:毫秒  ) -->
        <!-- 重复间隔时间 -->
        <property name="repeatInterval" value="3000"/>
        <!-- 重复次数 -->
        <property name="repeatCount" value="3"/>
    </bean>

    <!-- 3.创建Scheduler -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!-- 关联trigger -->
        <property name="triggers">
            <array>
                <ref bean="trigger"/>
            </array>
        </property>
    </bean>
</beans>

在主配置导入

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

以下是第二种方式,也是比较常用的方式。CronTrigger配置

2)编写applicationContext-quartz-cron.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.创建Job -->
    <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- 关联自己的任务 -->
        <property name="jobClass" value="com.jobs.MyJob"/>
    </bean>

    <!-- 2.创建Trigger: CronTrigger -->
    <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">
            <array>
                <ref bean="trigger"/>
            </array>
        </property>
    </bean>
</beans>

在实际开发中,我们使用定时任务经常会遇到一个问题:quartz的job中使用autowired注解注入的对象为空,这时候我们就要使用spring-quartz提供的AdaptableJobFactory类。

解决方法:
第一步:自定义一个类:

public class MyJobFactory extends AdaptableJobFactory {

    //这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入,这属于Spring的技术,不清楚的可以查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

第二步:在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">


    <!-- 创建一个JOB -->
    <bean id="JobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- 关联自己的任务 -->
        <property name="jobClass" value="com.jobs.PromotionJob"></property>
    </bean>


    <!-- 创建Trigger:ConTrigger-->
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <!-- 关联JobDetail -->
        <property name="JobDetail" ref="JobDetail"></property>
        <!-- 配置cron表达式 -->
        <property name="cronExpression" value="0/5 * * * * ? *"></property>
    </bean>



    <!-- com.jobs.MyJobFactory -->
    <bean id="jobFactory" class="com.jobs.MyJobFactory"></bean>



    <!-- 创建Scheduler对象 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

        <!-- 覆盖原有的jobFactory -->
        <property name="jobFactory" ref="jobFactory"></property>

        <!-- 关联trigger -->
        <property name="triggers">
            <array>
                <ref bean="trigger"/>
            </array>
        </property>
    </bean>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值