初识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. day01_虚拟机与主机之间ip配置

       虚拟机1: centos_ node1 虚拟机2:centos_node2 宿主主机虚拟机ip配置: vmnet1 来自为知笔记(Wiz)

  2. 安装 ambaria

    hadoop安装 wget http://public-repo-1.hortonworks.com/ambari/centos6/1.x/updates/1.2.4.9/ambari.repo cp ...

  3. Postman(调试工具)

    Postman Postman用法简介-Http请求模拟工具 时间 2015-09-26 23:52:00  博客园-原创精华区 原文  http://www.cnblogs.com/codingbl ...

  4. 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据

    1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...

  5. c/c++转义字符大全【转自互联网】

    将转义字符收集如下:转义字符 意义 ASCII码值(十进制) \a 响铃(BEL) 007 \b 退格(BS) 008 \f 换页(FF) 012 \n 换行(LF) 010 \r 回车(CR) 01 ...

  6. CSS, Sass, SCSS 关系

    Sass(Syntactically Awesome Style Sheets) ,是一种css预处理器和一种语言, 它可以用来定义一套新的语法规则和函数,以加强和提升CSS. 它有很多很好的特性,但 ...

  7. Android Market google play store帐号注册方法流程 及发布应用注意事项

    Android Market google play store帐号申请 注册方法流程 在 Google Play 中发布软件之前,您需要完成以下三项工作: 创建开发人员个人资料 接受开发人员分发协议 ...

  8. Android性能优化系列---管理你的app内存

     文章出处:http://developer.android.com/training/articles/memory.html#YourApp Random-access memory(RAM)在任 ...

  9. 洛谷P3966 [TJOI2013]单词(后缀自动机)

    传送门 统计单词出现次数……为啥大家都是写AC自动机的嘞……明明后缀自动机也能做的说…… 统计出现次数这个就直接按长度排序然后做个dp就好,这是SAM的板子的要求啊,不提了 然后考虑怎么让所有串之间隔 ...

  10. MVVM与Controller瘦身实践

    MVC是一个做iOS开发都知道的设计模式,也是Apple官方推荐的设计模式.实际上,Cocoa Touch就是按照MVC来设计的. 这里,我们先不讲MVC是什么,我们先来谈谈软件设计的一些原则或者说理 ...