初识quartz 并分析 项目中spring整合quartz的配置【原创+转载】
初识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的配置【原创+转载】的更多相关文章
- Maven项目中Spring整合Mybatis
Maven项目中Spring整合Mybatis 添加jar包依赖 spring需要的jar包依赖 <dependency> <groupId>org.springframewo ...
- Spring整合Quartz定时任务 在集群、分布式系统中的应用(Mysql数据库环境)
Spring整合Quartz定时任务 在集群.分布式系统中的应用(Mysql数据库环境) 转载:http://www.cnblogs.com/jiafuwei/p/6145280.html 单个Q ...
- Spring整合Quartz定时任务执行2次,Spring定时任务执行2次
Spring整合Quartz定时任务执行2次,Spring定时任务执行2次 >>>>>>>>>>>>>>>&g ...
- spring整合quartz并持久化
spring整合quartz有两种方式: 一.常见是使用配置文件,将定时任务保存到内存中 简单示例: <!-- 短信催还提醒任务调度 --> <bean id="overd ...
- Spring 整合 Quartz 实现动态定时任务
复制自:https://www.2cto.com/kf/201605/504659.html 最近项目中需要用到定时任务的功能,虽然Spring 也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能 ...
- 使用spring整合Quartz实现—定时器
使用spring整合Quartz实现—定时器(Maven项目做演示) 不基于特定的基类的方法 一,开发环境以及依赖的jar包 Spring 4.2.6.RELEASE Maven 3.3.9 Jdk ...
- 【转】Spring 整合 Quartz 实现动态定时任务
http://blog.csdn.net/u014723529/article/details/51291289 最近项目中需要用到定时任务的功能,虽然spring 也自带了一个轻量级的定时任务实现, ...
- Spring 整合 Quartz 实现动态定时任务(附demo)
最近项目中需要用到定时任务的功能,虽然Spring 也自带了一个轻量级的定时任务实现,但感觉不够灵活,功能也不够强大.在考虑之后,决定整合更为专业的Quartz来实现定时任务功能. 普通定时任务 首先 ...
- spring整合quartz框架
spring整合quartz: 网上也有很多教程,好多都是基于配置方式,我们使用当然怎么简单就怎么用,所以这里介绍基于注解方式整合quartz.前提:你需要有一个能运行的web项目. 1.引依赖: & ...
随机推荐
- 关于使用struts2跳转后css和js失效的解决方式
根据观察,主要是由于通过action跳转后的url会根据命名空间,自动跳转到命名空间子目录,使得当前引用的css和js查找不到,从而失效,根据这个原因,可使用四种办法解决: 1.使用struts2.x ...
- Maven jenkins +Jmeter自动化测试
Maven jenkins +Jmeter自动化测试 1. Jenkins中集成jmeter-maven插件 http://my.oschina.net/u/1377774/blog/168969 2 ...
- 机器学习前沿热点——Deep Learning
深度学习是机器学习研究中的一个新的领域,其动机在于建立.模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像.声音和文本.深度学习是无监督学习的一种. 深度学习的概念源于人工神经网络的 ...
- MySql集合查询
SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作. 集合操作主要包括并操作UNION.交操作INTERSECT.差操作EXCEPT. 注意,参加集合操作的各查询结果 ...
- CSS定位机制总结
1,CSS 有三种基本的定位机制:普通流.浮动和绝对定位.除非专门指定,否则所有框都在普通流中定位.2,普通流定位:块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来.行内框在 ...
- hdu1054
/* [题意] 给定一棵树,标记一节点,则与该节点所连的边都被标记,问最少需要标记多少个节点使得所有边都被标记: 或者说给定一个树型城堡,在交叉路口放一个士兵,则与该路口相连的路都被守住, 问最少需要 ...
- [WIP]Vue 基础
创建: 2019/05/30 https://cn.vuejs.org/v2/guide/ 安装 初期选择直接嵌入 <!-- 开发环境版本,包含了有帮助的命令行警告 --> <sc ...
- 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 ...
- java解析xml实例——获取天气信息
获取xml并解析其中的数据: package getweather.xml; import java.io.IOException; import java.util.HashMap; import ...
- checkbox,不选中传值
根据W3C的规则未选中的checkbox和禁用的控件不是有效控件,不会被POST.因此如果要未选中的checkbox表示值0的话,就不得不曲线完成了. 最近研究Zend Framework时候,发现其 ...