初识quartz 并分析 项目中spring整合quartz的配置【原创+转载】
2018年01月29日 12:08:07 守望dfdfdf 阅读数:114 标签: quartz 更多
个人分类: 工具 软件
编辑
版权声明:本文为博主原创文章,转载请注明文章链接。 https://blog.csdn.net/xiaoanzi123/article/details/79173113
之前接触一个小demo项目,当时忙于需求开发而只关注功能,没有注意配置,今天就拾起来分析一下,顺便接触新内容。
首先,关于quartz,之前没有接触过,近期在不同的项目模块中均有所看到这个quartz,那就必须学习了解下了。
Quartz是一个任务调度框架。比如你遇到这样的问题,想每月6号,自动给老妈发一封邮件,想每隔1分钟查询下有没有新的短消息等等。这些问题可以概括为在某个有规律的时间点干指定的事情。这个时间点需要一个触发动作,触发的条件由你来 配置定义,Quartz只负责到点了就开干。

创建你自己的类,实现org.quartz.Job接口。Job接口包含唯一的方法:
public voidexecute(JobExecutionContext context)throws JobExecutionException;
添加一些逻辑到execute()方法。一旦你配置好Job实现类并设定好调度时间表,Quartz将密切注意剩余时间。当调度程序确定该是通知你的作业的时候,Quartz框架将调用你Job实现类(作业类)上的execute()方法并允许做它该做的事情。无需报告任
何东西给调度器或调用任何特定的东西。仅仅执行任务和结束任务即可。如果配置你的作业在随后再次被调用,Quartz框架将在
恰当的时间再次调用它。

------------------以下内容摘录转载自-- https://www.cnblogs.com/yqw1994/p/6599562.html --------------------
------------------部分转载,更详细的quarz知识体系内容请 参照原文 ------------------------------
一个简单的示例
这里面的所有例子都是基于Quartz 2.2.1

package com.test.quartz;
import static org.quartz.DateBuilder.newDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;
import java.util.GregorianCalendar;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;

public class QuartzTest {
    public static void main(String[] args) {
        try {
            //创建scheduler
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //定义一个Trigger
            Trigger trigger = newTrigger().withIdentity("trigger1", "group1") //定义name/group
                .startNow()//一旦加入scheduler,立即生效
                .withSchedule(simpleSchedule() //使用SimpleTrigger
                    .withIntervalInSeconds(1) //每隔一秒执行一次
                    .repeatForever()) //一直执行,奔腾到老不停歇
                .build();
            //定义一个JobDetail
            JobDetail job = newJob(HelloQuartz.class) //定义Job类为HelloQuartz类,这是真正的执行逻辑所在
                .withIdentity("job1", "group1") //定义name/group
                .usingJobData("name", "quartz") //定义属性
                .build();
            //加入这个调度
            scheduler.scheduleJob(job, trigger);
            //启动之
            scheduler.start();
            //运行一段时间后关闭
            Thread.sleep(10000);
            scheduler.shutdown(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.test.quartz;
import java.util.Date;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloQuartz implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail detail = context.getJobDetail();
        String name = detail.getJobDataMap().getString("name");
        System.out.println("say hello to " + name + " at " + new Date());
    }
}

JobDetail & Job
JobDetail是任务的定义,而Job是任务的执行逻辑。在JobDetail里会引用一个Job Class定义。一个最简单的例子
public class JobTest {
    public static void main(String[] args) throws SchedulerException, IOException {
           JobDetail job=newJob()
               .ofType(DoNothingJob.class) //引用Job Class
               .withIdentity("job1", "group1") //设置name/group
               .withDescription("this is a test job") //设置描述
               .usingJobData("age", 18) //加入属性到ageJobDataMap
               .build();

           job.getJobDataMap().put("name", "quertz"); //加入属性name到JobDataMap

           //定义一个每秒执行一次的SimpleTrigger
           Trigger trigger=newTrigger()
                   .startNow()
                   .withIdentity("trigger1")
                   .withSchedule(simpleSchedule()
                       .withIntervalInSeconds(1)
                       .repeatForever())
                   .build();

           Scheduler sche=StdSchedulerFactory.getDefaultScheduler();
           sche.scheduleJob(job, trigger);

           sche.start();

           System.in.read();

           sche.shutdown();
    }
}

public class DoNothingJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("do nothing");
    }
}

这个例子很好的覆盖了Quartz最重要的3个基本要素:【这里是最重要的三点!!!】
Scheduler:调度器。所有的调度都是由它控制。
Trigger: 定义触发的条件。例子中,它的类型是SimpleTrigger,每隔1秒中执行一次(什么是SimpleTrigger下面会有详述)。
JobDetail&Job: JobDetail 定义的是任务数据,而真正的执行逻辑是在Job中,例子中是HelloQuartz。为什么设计成JobDetail + Job,不直接使用Job?这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。
从上例我们可以看出出,要定义一个任务,需要干几件事:
创建一个org.quartz.Job的实现类,并实现实现自己的业务逻辑。比如上面的DoNothingJob。
定义一个JobDetail,引用这个实现类
加入scheduleJob进行调度
Quartz调度一次任务,会干如下的事:
JobClass jobClass=JobDetail.getJobClass()
Job jobInstance=jobClass.newInstance()。

所以Job实现类,必须有一个public的无参构建方法。
jobInstance.execute(JobExecutionContext context)。JobExecutionContext是Job运行的上下文,可以获得Trigger、Scheduler、JobDetail的信息。
也就是说,每次调度都会创建一个新的Job实例,这样的好处是有些任务并发执行的时候,不存在对临界资源的访问问题——当然,如果需要共享JobDataMap的时候,还是存在临界资源的并发访问的问题。
JobDataMap
Job都次都是newInstance的实例,那我怎么传值给它? 比如我现在有两个发送邮件的任务,一个是发给"liLei",一个发给"hanmeimei",不能说我要写两个Job实现类LiLeiSendEmailJob和HanMeiMeiSendEmailJob。实现的办法是通过JobDataMap。
每一个JobDetail都会有一个JobDataMap。JobDataMap本质就是一个Map的扩展类,只是提供了一些更便捷的方法,比如getString()之类的。
我们可以在定义JobDetail,加入属性值,方式有二:
newJob().usingJobData("age", 18) //加入属性到ageJobDataMap

or

job.getJobDataMap().put("name", "quertz"); //加入属性name到JobDataMap

然后在Job中可以获取这个JobDataMap的值,方式同样有二:

public class HelloQuartz implements Job {
    private String name;

    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail detail = context.getJobDetail();
        JobDataMap map = detail.getJobDataMap(); //方法一:获得JobDataMap
        System.out.println("say hello to " + name + "[" + map.getInt("age") + "]" + " at "
                           + new Date());
    }

    //方法二:属性的setter方法,会将JobDataMap的属性自动注入
    public void setName(String name) {
        this.name = name;
    }
}

对于同一个JobDetail实例,执行的多个Job实例,是共享同样的JobDataMap,也就是说,如果你在任务里修改了里面的值,会对其他Job实例(并发的或者后续的)造成影响。
除了JobDetail,Trigger同样有一个JobDataMap,共享范围是所有使用这个Trigger的Job实例。
Scheduler
Scheduler就是Quartz的大脑,所有任务都是由它来设施。
Schduelr包含一个两个重要组件: JobStore和ThreadPool。
JobStore是会来存储运行时信息的,包括Trigger,Schduler,JobDetail,业务锁等。它有多种实现RAMJob(内存实现),JobStoreTX(JDBC,事务由Quartz管理),JobStoreCMT(JDBC,使用容器事务),ClusteredJobStore(集群实现)、TerracottaJobStore(什么是Terractta)。
ThreadPool就是线程池,Quartz有自己的线程池实现。所有任务的都会由线程池执行。
SchedulerFactory
SchdulerFactory,顾名思义就是来用创建Schduler了,有两个实现:DirectSchedulerFactory和 StdSchdulerFactory。前者可以用来在代码里定制你自己的Schduler参数。后者是直接读取classpath下的quartz.properties(不存在就都使用默认值)配置来实例化Schduler。通常来讲,我们使用StdSchdulerFactory也就足够了。
SchdulerFactory本身是支持创建RMI stub的,可以用来管理远程的Scheduler,功能与本地一样,可以远程提交个Job什么的。

----------------------------------------------------------------------- 转载引用结束线- --------------------------- -----------------------------------------------

记住三个步骤: 参考文章spring和quartz结合配置:【很好的文章,条理清晰:http://blog.csdn.net/u010648555/article/details/54891264】
1:定义工作任务的Job
2:定义触发器Trigger,并将触发器与工作任务绑定
3:定义调度器,并将Trigger注册到Scheduler

通过上述原文作者的详细描述,对quarz有了较为直观的认识,接下来就算去分析下目前的这个项目demo的配置文件。
目录结构如图:主要目的就是分析配置文件的配置执行流程。

现在看来这个demo是quartz和spring进行结合通过配置文件来实现上述总结的三个步骤,这就好理解了。
先看demoJob.xml文件:

<beans>

    <!-- quartz与spring整合  第二步  定义触发器的bean,定义一个Cron的Trigger,一个触发器只能和一个任务进行绑定 -->
    <bean id="demoJobTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
         <!-- 指定Tirgger绑定的Job -->
        <property name="jobDetail" ref="demoJob_jobDetail" />
         <!-- 指定Cron 的表达式 ,每隔多久运行多少次 -->
        <property name="cronExpression" value="10/59 * * * * ?" />
    </bean>

    <!--quartz与spring整合  第一步  : 定义任务的bean(工作任务的job) -->
    <bean id="demoJob_jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject">
             <bean class="com.xxxx.zhejiang.hangzhou.xxxx.tasks.DemoJob"></bean>
        </property>
        <property name="targetMethod" value="doJob" />
        <property name="concurrent" value="false" />
    </bean>

</beans>

可以看出前两步在这里都已经完成了,定义job,然后job连接到触发器trigger里面。然后走到下面的trigger.xml

<beans>
    <bean id="jobList" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <ref bean="demoJobTrigger" />
            </list>
        </constructor-arg>
    </bean>
</beans>

然后接下来就是第三步,把已经连接好job的trigger  连接到  调度器schedule里面,接下来quartz.xml

<beans>

    <!-- quartz与spring整合  第三步.定义调度器,并将Trigger注册到调度器中 --> -->
    <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
    <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers" ref="jobList" />
        <property name="quartzProperties">
            <props>
                <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
                <prop key="org.quartz.threadPool.threadCount">50</prop>
                <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>
                <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
            </props>
        </property>
        <property name="globalJobListeners">
            <list>
                <ref bean="jobListeners" />
            </list>
        </property>
    </bean>
    <bean id="jobListeners" class="com.xxxx.job.TaskListerner" />

</beans>

三个步骤之间的连接过程我在代码中已经用颜色来进行区分。以后  com.xxxx.zhejiang.hangzhou.xxxx.tasks.DemoJob 中的doJob方法就会按照设定好的定时任务有规律的执行。

初识quartz 并分析 项目中spring整合quartz的配置【原创+转载】的更多相关文章

  1. Maven项目中Spring整合Mybatis

    Maven项目中Spring整合Mybatis 添加jar包依赖 spring需要的jar包依赖 <dependency> <groupId>org.springframewo ...

  2. Spring整合Quartz定时任务 在集群、分布式系统中的应用(Mysql数据库环境)

    Spring整合Quartz定时任务 在集群.分布式系统中的应用(Mysql数据库环境)   转载:http://www.cnblogs.com/jiafuwei/p/6145280.html 单个Q ...

  3. Spring整合Quartz定时任务执行2次,Spring定时任务执行2次

    Spring整合Quartz定时任务执行2次,Spring定时任务执行2次 >>>>>>>>>>>>>>>&g ...

  4. spring整合quartz并持久化

    spring整合quartz有两种方式: 一.常见是使用配置文件,将定时任务保存到内存中 简单示例: <!-- 短信催还提醒任务调度 --> <bean id="overd ...

  5. Spring 整合 Quartz 实现动态定时任务

    复制自:https://www.2cto.com/kf/201605/504659.html 最近项目中需要用到定时任务的功能,虽然Spring 也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能 ...

  6. 使用spring整合Quartz实现—定时器

    使用spring整合Quartz实现—定时器(Maven项目做演示) 不基于特定的基类的方法 一,开发环境以及依赖的jar包 Spring 4.2.6.RELEASE Maven 3.3.9 Jdk ...

  7. 【转】Spring 整合 Quartz 实现动态定时任务

    http://blog.csdn.net/u014723529/article/details/51291289 最近项目中需要用到定时任务的功能,虽然spring 也自带了一个轻量级的定时任务实现, ...

  8. Spring 整合 Quartz 实现动态定时任务(附demo)

    最近项目中需要用到定时任务的功能,虽然Spring 也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之后,决定整合更为专业的Quartz来实现定时任务功能. 普通定时任务 首先 ...

  9. spring整合quartz框架

    spring整合quartz: 网上也有很多教程,好多都是基于配置方式,我们使用当然怎么简单就怎么用,所以这里介绍基于注解方式整合quartz.前提:你需要有一个能运行的web项目. 1.引依赖: & ...

随机推荐

  1. IE和W3c盒模型

    盒子模型是css中一个重要的概念,理解了盒子模型才能更好的排版.其实盒子模型有两种,分别是 ie 盒子模型和标准 w3c 盒子模型.他们对盒子模型的解释各不相同,先来看看我们熟知的标准盒子模型: 从上 ...

  2. PopupWindow-----listview item的点击出现PopupWindow

    /** * 设置listview item的点击事件 */ lv_app_manager.setOnItemClickListener(new OnItemClickListener() { @Ove ...

  3. EchoServer和EchoClient模型的改进1之多线程

    在之前的EchoServer模型个EchoClient模型中,客户端和服务端只是单纯的一一对应的关系,如果存在多个客户端和一个服务端,这就需要具体处理了.在这里我们明显想到的第一种方案是使用多线程处理 ...

  4. DOM 中 Property 和 Attribute 的区别(转)

    property 和 attribute非常容易混淆,两个单词的中文翻译也都非常相近(property:属性,attribute:特性),但实际上,二者是不同的东西,属于不同的范畴. property ...

  5. BZOJ4085: [Sdoi2015]音质检测

    BZOJ4085: [Sdoi2015]音质检测 由于这题太毒了,导致可能会被某些人卡评测,于是成了一道权限题... 本蒟蒻表示没钱氪金... 但是可以去洛谷/Vijos搞搞事... 但是洛谷上只能评 ...

  6. typeof用法

    typeof的运算数未定义,返回的就是 "undefined". 运算数为数字 typeof(x) = "number" 字符串 typeof(x) = &qu ...

  7. 3、Linux下配置Java环境

    转载:http://blog.sina.com.cn/s/blog_c5a35e780102wtxl.html 生物信息很多软件都是用java写的,所以需要在linux上配置java运行环境.平台上的 ...

  8. Spring Boot 高效数据聚合之道

    项目地址和示例代码: https://github.com/lvyahui8/spring-boot-data-aggregator 背景 接口开发是后端开发中最常见的场景, 可能是RESTFul接口 ...

  9. Jenkins配置有用摘抄笔记

    使用jenkins配置.net mvc5网站自动构建全过程记录  转自:http://www.cnblogs.com/baiyunchen/p/4724350.html 持续集成是个简单重复劳动,人来 ...

  10. Head First HTML与CSS(第2版) 中文pdf扫描版

    是不是已经厌倦了那些深奥的HTML书?你可能在抱怨,只有成为专家之后才能读懂那些书.那么,找一本新修订的<Head First HTML与CSS(第2版)>吧,来真正学习HTML.你可能希 ...