初识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.引依赖: & ...
随机推荐
- CentOS7下yum方式安装mysql5.6
在Centos7中用MariaDB代替了mysql数据库.所以在新安装MySQL前必须做好对系统的清理工作. 一.清理CentOS7下的MariaDB. [root@localhost ~]#rpm ...
- Java探索之旅(15)——包装类和字符类
1.包装类 ❶出于对性能的考虑,并不把基本数据类型作为对象使用,因为适用对象需要额外的系统花销.但是某些Java方法,需要对象作为参数,例如数组线性表ArrayList.add(Object).Jav ...
- 并发设计模式和锁优化以及jdk8并发新特性
1 设计模式 (1) 单例模式 保证一个类只能一个对象实现.正常的单例模式分为懒汉式和饿汉式,饿汉式就是把单例声明称static a=new A(),系统第一次调用的时候生成(包括调用该类的其他静态资 ...
- Unity编辑器的扩展:IMGUI
IMGUI 介绍 所有关于 Editor 的相关 UI,包括 Inspector.Hierarchy.Window.Game 视图上动态创建的那些半透明 UI.还有 Scene 视图上可添加的辅助显示 ...
- Linux服务器监控工具--Nmon介绍
一.Nmon介绍(详细请参考百度百科) 是一款分析 AIX 和 Linux 性能的免费工具,这个高效的工具可以工作于任何哑屏幕.telnet 会话.甚至拨号线路.另外,它并不会消耗大量的 CPU 周期 ...
- swiper实现左右滑动图片
ref:http://www.swiper.com.cn/usage/index.html help:https://segmentfault.com/a/1190000002962202 src: ...
- Umbraco安装过程中出现的问题以及调试
在VS2015中使用NuGet安装完UmbracoCms后,按Ctrl+F5运行程序来完成安装UmbracoCms的过程中,发现一直在安装但是没有反应 估计是出现了错误.所以我到项目所在的文件夹中查找 ...
- ubuntu下apache2的cgi-bin中以root权限运行程序
一,安装apache2 sudo apt-get install apache2 二.配置cgi-bin sudo chmod 777 /var/www/html sudo vim /etc/apac ...
- Eclipse超级有用的快捷键
1.Alt + Shift + R 重构 2.Ctrl + F11 运行并调试程序 3.Ctrl + Shift + O 自动导入包 4.Ctrl + Shift + F 格式化代码 5.F5 调试模 ...
- etcd代理组件的开发思想
最近在一个项目中,需要使用到etcd集群来实现服务发现的功能,目的是统一管理相应的服务资源,同时也可对资源做一定的负载均衡策略.然而,项目中使用的技术栈是C++语言,github上没有合适的C++开源 ...