初识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. 关于使用struts2跳转后css和js失效的解决方式

    根据观察,主要是由于通过action跳转后的url会根据命名空间,自动跳转到命名空间子目录,使得当前引用的css和js查找不到,从而失效,根据这个原因,可使用四种办法解决: 1.使用struts2.x ...

  2. Maven jenkins +Jmeter自动化测试

    Maven jenkins +Jmeter自动化测试 1. Jenkins中集成jmeter-maven插件 http://my.oschina.net/u/1377774/blog/168969 2 ...

  3. 机器学习前沿热点——Deep Learning

    深度学习是机器学习研究中的一个新的领域,其动机在于建立.模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像.声音和文本.深度学习是无监督学习的一种. 深度学习的概念源于人工神经网络的 ...

  4. MySql集合查询

    SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作. 集合操作主要包括并操作UNION.交操作INTERSECT.差操作EXCEPT. 注意,参加集合操作的各查询结果 ...

  5. CSS定位机制总结

    1,CSS 有三种基本的定位机制:普通流.浮动和绝对定位.除非专门指定,否则所有框都在普通流中定位.2,普通流定位:块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来.行内框在 ...

  6. hdu1054

    /* [题意] 给定一棵树,标记一节点,则与该节点所连的边都被标记,问最少需要标记多少个节点使得所有边都被标记: 或者说给定一个树型城堡,在交叉路口放一个士兵,则与该路口相连的路都被守住, 问最少需要 ...

  7. [WIP]Vue 基础

    创建: 2019/05/30 https://cn.vuejs.org/v2/guide/  安装 初期选择直接嵌入 <!-- 开发环境版本,包含了有帮助的命令行警告 --> <sc ...

  8. The Knuth-Morris-Pratt Algorithm in my own words(转)

    origianl For the past few days, I’ve been reading various explanations of the Knuth-Morris-Pratt str ...

  9. java解析xml实例——获取天气信息

    获取xml并解析其中的数据: package getweather.xml; import java.io.IOException; import java.util.HashMap; import ...

  10. checkbox,不选中传值

    根据W3C的规则未选中的checkbox和禁用的控件不是有效控件,不会被POST.因此如果要未选中的checkbox表示值0的话,就不得不曲线完成了. 最近研究Zend Framework时候,发现其 ...