文档章节

Quartz与Spring的整合使用——创建JobDetail的方式及Trigger

BakerZhu
 BakerZhu
发布于 2017/10/25 16:01
字数 1436
阅读 203
收藏 1

之前说到过Quartz的基本使用(猛戳这里看文章),在实际使用中,我们通常会将定时任务交由spring容器来管理,所以今天我们来说说Quartz与spring的整合。

咱们还是按照Quartz的三大元素的顺序来聊聊整合使用。

作业任务

在spring中对于Quartz的作业任务管理主要提供了两种方式,JobDetailFactoryBean和MethodInvokingJobDetailFactoryBean,它们都在org.springframework.scheduling.quartz这个包下。下面我们来看看它们的使用。

  • JobDetailFactoryBean

spring对这个类的解释为:A Spring FactoryBean for creating a Quartz JobDetail instance, supporting bean-style usage for JobDetail configuration. 
一个用于创建Quartz JobDetail实例的,支持以bean定义风格来配置JobDetail的工厂bean。

对于在spring中的使用也是很简单,首先我们需要创建一个具体的作业任务的实现类。使用JobDetailFactoryBean来管理作业任务时,我们的作业任务实现类需要继承QuartzJobBean类,并覆盖其executeInternal方法。就像下面这样。

public class SimpleJob extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext arg0)
            throws JobExecutionException {
        System.out.println("现在时间为:"+new Date());
        //可以通过上下文获取到JobDataMap,这里面可以存放一些参数类型的数据
        JobDataMap dataMap=arg0.getMergedJobDataMap();
        String wish=(String) dataMap.get("wish");
        System.out.println(wish);
    }
}

然后就在spring容器中如下配置:

<bean id="jobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <!-- 参考源码,我们可以看到属性jobClass为Class类型,所以不能使用ref来引用一个bean,否则就会因为不能将bean转换为Class类型而出现异常。
        <property name="jobClass" ref="simpleJob"/>
        必须使用value对jobClass赋值。 
        <property name="jobClass" value="com.earl.quartz.spring.job.SimpleJob"/>    
    -->
    <property name="jobClass" value="com.earl.quartz.spring.job.SimpleJob"/>
    <!-- 这里设置的jobDataAsMap可以传递一些参数给作业任务 -->
    <property name="jobDataAsMap">
        <map>
            <entry key="wish" value="hello"/>
        </map>
    </property>
</bean>
  • MethodInvokingJobDetailFactoryBean

spring对这个类的解释:FactoryBean that exposes a JobDetail object which delegates job execution to a specified (static or non-static) method. 
这个FactoryBean提供JobDetail对象,这个对象可以指定作业任务的执行方法。

因为可以指定作业调度时执行的内容,所以使用起来就比JobDetailFactoryBean更加的灵活方便。首先我们还是创建一个作业任务的具体实现类,这个实现类就不需要继承或实现其他的父类,只需要将我们想要执行的作业任务声明在具体的方法中即可。如下:

public class ExampleJob{
    public void execute(){
        System.out.println("现在是"+new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒").format(new Date()));
    }
}

然后在spring容器中如下配置即可:

<!-- 
    如果两个触发器触发同一个作业,那么第二个作业可能在第一个作业完成之前被触发。
    将作业类实现StatefulJob接口就可以避免这种情况。
    将concurrent设置为false可以避免并发的发生。
-->
<!-- 使用MethodInvokingJobDetailFactoryBean来创建作业对象 -->
<bean id="exampleJob" class="com.earl.quartz.spring.job.ExampleJob"/>
<bean id="methodInvokingJobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 目标对象,指的是作业任务的实现类 -->
<property name="targetObject" ref="exampleJob"/>
<!-- 目标方法,指的是指定实现类中的哪个方法作为调度时的执行方法 -->
<property name="targetMethod" value="execute"/>
<!-- 是否并发 -->
<property name="concurrent" value="false"/>
</bean>

以上就是作业任务的相关内容,下面我们来看看触发器这个可爱的小东东。

触发器

在spring中,触发器也分为simpleTrigger和cronTrigger,而且它们的使用也是非常简单,只需要配置一个bean元素即可。下面我们分别看看它们两者的配置:

  • simpleTrigger
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <!-- 这里的JobDetail指的就是我们配置的作业任务的bean -->
    <property name="jobDetail" ref="methodInvokingJobDetailFactoryBeanExample" />
    <!-- 延迟5秒开始 -->
    <property name="startDelay" value="5000"></property>
    <!-- 每3秒重复一次 -->
       <property name="repeatInterval" value="3000"></property>     
</bean>
  • cronTrigger
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <!-- 这里的JobDetail指的就是我们配置的作业任务的bean -->
    <property name="jobDetail" ref="jobDetailFactoryBeanExample"/>
    <!--cronExpression,cron表达式-->
    <property name="cronExpression" value="40 52 17 * * ?"/>
</bean>

以上就是触发器的基本配置,上述两个触发器的工厂bean还有一些其他的属性,例如jobDataMap,priority等等。如果有需要,您可以参考相关的文档。

调度程序

最后,最简单的莫过于作业调度程序了,在spring中只需要这样配置即可:

<bean id="startQuartz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
    <!--指定使用哪些触发器,spring会去调度触发相应的触发器,进而对作业任务进行调度处理-->
    <property name="triggers">
        <list>
<!--                <ref bean="simpleTrigger"/> -->
            <ref bean="cronTrigger"/>
        </list>
    </property>
</bean>

总结

以上就是对Quartz与Spring的整合使用的基本介绍了。总体来说,Quartz的定时任务功能已经很强大了,而spring对其的整合更是让程序员在使用定时任务是如虎添翼。对于Quartz来说还有很多其他的功能,例如定时文件扫描,定时发送邮件等等,之后在另外一篇文章中再进行详细介绍。

猛戳这里下载源代码 
说明:本文介绍的是Quartz与Spring的整合使用,所以请参考源码时关注com.earl.quartz.spring包下内容即可,其他可自行忽略。

 

如何从Job中获取ApplicationContext对象:

在xml配置文件中 加入applicationContextSchedulerContextKey配置

    <bean  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

        <property name="triggers">
            <list>
             <!--   <ref bean="simpleTrigger" />-->
                <ref bean="cronTrigger" />
            </list>
        </property>
        <property name="applicationContextSchedulerContextKey" value="applicationContextKey"/>
    </bean>

value的值 用于Job中获取application上下文对象。 即设置 APPLICATION_CONTEXT_KEY 的值

public class ScheduledJob extends QuartzJobBean {
    private static final String APPLICATION_CONTEXT_KEY = "applicationContextKey";

    private AnotherBean anotherBean;
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        ApplicationContext applicationContext = null;
        try{
            applicationContext = getApplicationContext(context);
        }catch (Exception e){
            e.printStackTrace();
        }
        if(applicationContext != null){
            System.out.println("applicationContext");
            ((AnotherBean)(applicationContext.getBean("anotherBean"))).printAnotherMessage();
        }
    }
    private ApplicationContext getApplicationContext(JobExecutionContext context) throws Exception {
        ApplicationContext appCtx = null;
        appCtx = (ApplicationContext) context.getScheduler().getContext().get(APPLICATION_CONTEXT_KEY);
        if (appCtx == null) {
            throw new JobExecutionException("No application context available in scheduler context for key \"" + APPLICATION_CONTEXT_KEY + "\"");
        }
        return appCtx;
    }
}

 

 

 

© 著作权归作者所有

BakerZhu
粉丝 108
博文 517
码字总数 423077
作品 0
通州
程序员
私信 提问
使用cronTriggerBean子类,动态设置cronExpression(quartz +...

Quartz的使用前准备: 1.引入必要的jar包: quartzallxxx.jar 或者quartz_xxx.jar slf4japixx.jar quartz所需要的日志工具 quartz知识简单了解:2.quartz的两种作业存储方式: RAMJobStore,...

gerry_pang
2013/08/11
4.8K
0
Spring Quartz的原理

Quartz是一个大名鼎鼎的Java版开源定时调度器,功能强悍,使用方便。 一、核心概念 Quartz的原理不是很复杂,只要搞明白几个概念,然后知道如何去启动和关闭一个调度程序即可。 1、Job 表示一...

laigous
2014/05/05
3.3K
1
项目ITP(六) spring4.0 整合 Quartz 实现动态任务调度

2014-05-18 12:51 by Jeff Li 前言   系列文章:[传送门]   项目需求:      http://www.cnblogs.com/Alandre/p/3733249.html      上一博客写的是基本调度,后来这只能用于,...

泥沙砖瓦浆木匠
2014/05/18
9.1K
0
用quartz实现多任务动态加载

Quartz是什么 Quartz是一个用Java编写的任务调度框架,任务调度是什么,举例说明:比如我们需要在每个星期四下午三点时候发周报,我们需要一个系统在两点半的时候给我们一个发周报的提醒,这...

随影求是
2012/05/03
3.2K
0
Spring Cloud 2.x系列之springboot集成quartz

java设计模式之观察者模式 一大波视频分享 Mysql代理中间件Atlas安装和配置 在做项目时有时候会有定时器任务的功能,比如某某时间应该做什么,多少秒应该怎么样之类的。定时任务常用的业务场...

技术小能手
2018/10/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JS基础-该如何理解原型、原型链?

JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对这个...

OBKoro1
33分钟前
4
0
高防CDN的出现是为了解决网站的哪些问题?

高防CDN是为了更好的服务网络而出现的,是通过高防DNS来实现的。高防CDN是通过智能化的系统判断来路,再反馈给用户,可以减轻用户使用过程的复杂程度。通过智能DNS解析,能让网站访问者连接到...

云漫网络Ruan
今天
13
0
聊聊Tomcat中的连接器(Connector)

上期回顾 上一篇文章《Tomcat在SpringBoot中是如何启动的》从main方法启动说起,窥探了SpringBoot是如何启动Tomcat的,在分析Tomcat中我们重点提到了,Tomcat主要包括2个组件,连接器(Conne...

木木匠
今天
10
0
OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
2.5K
22
SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
44
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部