quarzy实现定时任务以及和spring整合
来源:互联网 发布:mac怎么设置邮箱imap 编辑:程序博客网 时间:2024/05/08 19:56
这里是 Quartz在Spring中的简单使用 http://yangpanwww.iteye.com/blog/797563
本文将简单介绍在没有 Spring 的时候..如何来使用 Quartz...
这里跳过 Quartz 的其他介绍。如果想更加输入的了解 Quartz,大家可以点击下载Quartz的帮助文档。
Quartz 和 Web 集成应用
第一步: 导入quartz包..这个不用说吧..放到工程的 lib 下面即可
第二步: 添加相应文件和修改web.xml文件的配置.
添加 quartz.properties 和 quartz_jobs.xml 到 src 下面
quartz.properties文件如下:
- #===============================================================
- #Configure Main Scheduler Properties
- #===============================================================
- org.quartz.scheduler.instanceName = QuartzScheduler
- org.quartz.scheduler.instanceId = AUTO
- #===============================================================
- #Configure ThreadPool
- #===============================================================
- org.quartz.threadPool.threadCount = 5
- org.quartz.threadPool.threadPriority = 5
- org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
- #===============================================================
- #Configure JobStore
- #===============================================================
- org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
- #===============================================================
- #Configure Plugins
- #===============================================================
- org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
- org.quartz.plugins.xml.JobInitializationPlugin = quartz_jobs.xml
- org.quartz.plugin.jobInitializer.overWriteExistingJobs = false
- org.quartz.plugin.jobInitializer.validating = false
- org.quartz.plugin.jobInitializer.failOnFileNotFound =true
quartz_jobs.xml 文件如下
- <?xml version="1.0" encoding="UTF-8"?>
- <quartz>
- <job>
- <job-detail>
- <name>GatherJob</name>
- <group>DEFAULT</group>
- <description>GatherJob</description>
- <job-class>net.sf.rain.gather.quartz.GatherJob</job-class>
- <volatility>false</volatility>
- <durability>false</durability>
- <recover>false</recover>
- </job-detail>
- <trigger>
- <cron>
- <name>RunQuartzJobTrigger</name>
- <group>DEFAULT</group>
- <description>RunQuartzJobTrigger</description>
- <job-name>RunQuartzJob</job-name>
- <job-group>DEFAULT</job-group>
- <!-- <cron-expression>0/60 * * * * ?</cron-expression> -->
- <cron-expression>0 0 3 * * ?</cron-expression>
- </cron>
- </trigger>
- </job>
- </quartz>
注意文件中的配置要正确。比如 job-class 等等。
web.xml的配置:
从 2.3 版本的 Servlet API 开始,你能创建监听器,由容器在其生命周期中的某个特定时间回调。其中的一个监听器接口叫做 java.servlet.ServletContextListener,
WEB.xml
- <!-- ====================== Quartz config start ====================== -->
- <context-param>
- <param-name>config-file</param-name>
- <param-value>/quartz.properties</param-value>
- </context-param>
- <context-param>
- <param-name>shutdown-on-unload</param-name>
- <param-value>true</param-value>
- </context-param>
- <context-param>
- <param-name>start-scheduler-on-load</param-name>
- <param-value>true</param-value>
- </context-param>
- <!-- 默认情况下配置 Quzrtz 自带的监听器..但是真正项目开发中。我们是否开启定时任务应该是人工配置,所以我们需要自定义监听器 -->
- <!--
- <listener>
- <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
- </listener>
- -->
- <listener>
- <listener-class>
- net.sf.rain.gather.quartz.QuartzServletContextListener
- </listener-class>
- </listener>
- <!-- ====================== Quartz config end ====================== -->
下面我们将实现这个监听器 QuartzServletContextListener
- package net.sf.rain.gather.quartz;
- import javax.servlet.ServletContext;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.quartz.SchedulerException;
- import org.quartz.impl.StdSchedulerFactory;
- public class QuartzServletContextListener implements ServletContextListener {
- private static Log _log = LogFactory.getLog(QuartzServletContextListener.class);
- public static final String QUARTZ_FACTORY_KEY = "org.quartz.impl.StdSchedulerFactory.KEY";
- private ServletContext ctx = null;
- private StdSchedulerFactory factory = null;
- /**
- * Called when the container is shutting down.
- */
- public void contextDestroyed(ServletContextEvent sce) {
- try {
- factory.getDefaultScheduler().shutdown();
- } catch (SchedulerException ex) {
- _log.error("Error stopping Quartz", ex);
- }
- }
- /**
- * 容器的第一次启动时调用
- */
- public void contextInitialized(ServletContextEvent sce) {
- ctx = sce.getServletContext();
- try {
- factory = new StdSchedulerFactory();
- // Start the scheduler now
- //设置容器启动时不立即启动定时器,而是到后台人工启动
- //factory.getScheduler().start();
- _log.info("Storing QuartzScheduler Factory at" + QUARTZ_FACTORY_KEY);
- ctx.setAttribute(QUARTZ_FACTORY_KEY, factory);
- } catch (Exception ex) {
- _log.error("Quartz failed to initialize", ex);
- }
- }
- }
下面的Action将管理定时器的状态
- package net.sf.rain.gather.quartz;
- import java.io.PrintWriter;
- import javax.servlet.ServletContext;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.apache.commons.lang.StringUtils;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.struts.action.Action;
- import org.apache.struts.action.ActionForm;
- import org.apache.struts.action.ActionForward;
- import org.apache.struts.action.ActionMapping;
- import org.quartz.Scheduler;
- import org.quartz.SchedulerException;
- import org.quartz.impl.StdSchedulerFactory;
- /**
- *
- * 调度器管理
- *
- * @author 妞见妞爱
- *
- */
- public class GatherJobAction extends Action{
- private static Log _log = LogFactory.getLog(GatherJobAction.class);
- public ActionForward execute(ActionMapping mapping, ActionForm form,
- HttpServletRequest request, HttpServletResponse response)
- throws Exception {
- request.setCharacterEncoding("UTF-8");
- response.setContentType("text/html;charset=UTF-8");
- String action = request.getParameter("action");
- String retMsg = "Parameter Error: action is null";
- if (StringUtils.isNotBlank(action)) {
- ServletContext ctx = request.getSession().getServletContext();
- // Retrieve the factory from the ServletContext
- StdSchedulerFactory factory = (StdSchedulerFactory)ctx.getAttribute(QuartzServletContextListener.QUARTZ_FACTORY_KEY);
- // Retrieve the scheduler from the factory
- Scheduler scheduler = factory.getScheduler();
- if ("start".equals(action)) {
- // Start the scheduler
- try {
- if (!scheduler.isStarted()) {
- scheduler.start();
- }
- retMsg = "Quartz Successful to startup";
- } catch (SchedulerException ex) {
- _log.error("Error starting Quartz", ex);
- retMsg = "Quartz failed to startup";
- }
- }else if("stop".equals(action)){
- try {
- if (scheduler.isStarted()) {
- scheduler.shutdown();
- }
- retMsg = "Quartz Successful to stopping";
- } catch (SchedulerException ex) {
- _log.error("Error stopping Quartz", ex);
- retMsg = "Quartz failed to stopping";
- }
- }else { //查看调度器的状态
- if (scheduler.isStarted()) {
- retMsg = "Quartz is Started";
- }else {
- retMsg = "Quartz is Stoped";
- }
- }
- }
- PrintWriter out = response.getWriter();
- out.print(retMsg);
- out.flush();
- out.close();
- return null;
- }
- }
Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。本系统结合通过 Spring 来集成 Quartz 。
Quartz 下载地址 :
http://grepcode.com/snapshot/repo1.maven.org/maven2/org.quartz-scheduler/quartz/1.7.3
首先下载包 :quartz-1.7.3.jar (我上传到附件咯,嘿嘿)
把包放到 lib 里面。
applicationContext.xml:
- <!-- Timer schedule -->
- <!--要调度的对象-->
- <bean id="jobBean" class="net.xsbiz.common.MakeHtml" />
- <bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
- <property name="targetObject" ref="jobBean" />
- <property name="targetMethod" value="execute" />
- <!--将并发设置为false-->
- <property name="concurrent" value="false" />
- </bean>
- <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
- <property name="jobDetail" ref="jobDetail" />
- <!--表达式,我的是每 30 执行一次-->
- <property name="cronExpression" value="0/30 * * * * ?" />
- </bean>
- <!-- 总管理类如果将lazy-init='false'那么容器启动就会执行调度程序 -->
- <bean id="startQuertz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" >
- <property name="triggers">
- <list>
- <!--作业调度器,list下可加入其他的调度器-->
- <ref bean="trigger" />
- </list>
- </property>
- </bean>
web.xml:
- <!-- 设置Spring的监听,项目启动时候初始化 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- 指定Spring配置文件的路径 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
- </context-param>
MakeHtml.java :
- //调用的类
- public class MakeHtml {
- //调用的方法
- public void execute(){
- //需要做的事情
- }
- public static void main(String[] args) {
- System.out.println("----begin---");
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- // 如果配置文件中将startQuertz bean的lazy-init设置为false 则不用实例化
- context.getBean("startQuertz");
- System.out.print("----end---");
- }
- }
1 、JobDetail : JobDetail 是一个具体的类。
2、Trigger :触发器,它用于定义 Job 何时执行。最常用的是 SimpleTrigger 和 CronTrigger 。一般来说,如果你需要在一个固定的时间和重复次数或者一个固定的间隔时间,那么 SimpleTrigger 比较合适;如果你有许多复杂的作业调度,那么 CronTrigger 比较合适。CronTrigger 和 Unix 的 cron 机制基本一样,我们需要的只是一个 cron 表达式。比如“ 0 0 12 * * ? ”会在每天中午 12 点触发 执行;“ 0 15 10 ? * 6L ”会在每个月的最后一个星期五的早上 10:15 触发 Job 执行。
3、 Scheduler 和 SchedulerFactory : Scheduler 负责管理 Trigger 、调度 Job , SchedulerFactory 则是 Scheduler 工厂,负责生成Scheduler 。
基本上实现起来都容易,只是表达式。。有点。。我到网上搜索了下。。整理放到下面:
字段名 允许的值 允许的特殊字符
秒
0-59
, - * /
分
0-59
, - * /
小时
0-23
, - * /
日
1-31
, - * ? / L W C
月
1-12 or JAN-DEC
, - * /
周几
1-7 or SUN-SAT
, - * ? / L C #
年 (可选字段)
empty, 1970-2099
, - * /
'*' 字符可以用于所有字段,在“分”字段中设为"*"表示"每一分钟"的含义。
'?' 字符可以用在“日”和“周几”字段. 它用来指定 '不明确的值'. 这在你需要指定这两个字段中的某一个值而不是另外一个的时候会被用到。在后面的例子中可以看到其含义。
'-' 字符被用来指定一个值的范围,比如在“小时”字段中设为"10-12"表示"10点到12点".
',' 字符指定数个值。比如在“周几”字段中设为"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday".
'/' 字符用来指定一个值的的增加幅度. 比如在“秒”字段中设置为"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"则表示"第5, 20, 35, 和 50". 在'/'前加"*"字符相当于指定从0秒开始. 每个字段都有一系列可以开始或结束的数值。对于“秒”和“分”字段来说,其数值范围为0到59,对于“小时”字段来说其为0到23, 对于“日”字段来说为0到31, 而对于“月”字段来说为1到12。"/"字段仅仅只是帮助你在允许的数值范围内从开始"第n"的值。 因此对于“月”字段来说"7/6"只是表示7月被开启而不是“每六个月”, 请注意其中微妙的差别。
'L'字符可用在“日”和“周几”这两个字段。它是"last"的缩写, 但是在这两个字段中有不同的含义。例如,“日”字段中的"L"表示"一个月中的最后一天" —— 对于一月就是31号对于二月来说就是28号(非闰年)。而在“周几”字段中, 它简单的表示"7" or "SAT",但是如果在“周几”字段中使用时跟在某个数字之后, 它表示"该月最后一个星期×" —— 比如"6L"表示"该月最后一个周五"。当使用'L'选项时,指定确定的列表或者范围非常重要,否则你会被结果搞糊涂的。
'W' 可用于“日”字段。用来指定历给定日期最近的工作日(周一到周五) 。比如你将“日”字段设为"15W",意为: "离该月15号最近的工作日"。因此如果15号为周六,触发器会在14号即周五调用。如果15号为周日, 触发器会在16号也就是周一触发。如果15号为周二,那么当天就会触发。然而如果你将“日”字段设为"1W", 而一号又是周六, 触发器会于下周一也就是当月的3号触发,因为它不会越过当月的值的范围边界。'W'字符只能用于“日”字段的值为单独的一天而不是一系列值的时候。
'L'和'W'可以组合用于“日”字段表示为'LW',意为"该月最后一个工作日"。
'#' 字符可用于“周几”字段。该字符表示“该月第几个周×”,比如"6#3"表示该月第三个周五( 6表示周五而"#3"该月第三个)。再比如: "2#1" = 表示该月第一个周一而 "4#5" = 该月第五个周三。注意如果你指定"#5"该月没有第五个“周×”,该月是不会触发的。
'C' 字符可用于“日”和“周几”字段,它是"calendar"的缩写。它表示为基于相关的日历所计算出的值(如果有的话)。如果没有关联的日历, 那它等同于包含全部日历。“日”字段值为"5C"表示"日历中的第一天或者5号以后",“周几”字段值为"1C"则表示"日历中的第一天或者周日以后"。
对于“月份”字段和“周几”字段来说合法的字符都不是大小写敏感的。
下面是一些完整的例子:
表达式 含义"0 0 12 * * ?"
每天中午十二点触发
"0 15 10 ? * *"
每天早上10:15触发
"0 15 10 * * ?"
每天早上10:15触发
"0 15 10 * * ? *"
每天早上10:15触发
"0 15 10 * * ? 2005"
2005年的每天早上10:15触发
"0 * 14 * * ?"
每天从下午2点开始到2点59分每分钟一次触发"0 0/5 14 * * ?"
每天从下午2点开始到2:55分结束每5分钟一次触发"0 0/5 14,18 * * ?"
每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发"0 0-5 14 * * ?"
每天14:00至14:05每分钟一次触发"0 10,44 14 ? 3 WED"
三月的每周三的14:10和14:44触发"0 15 10 ? * MON-FRI"
每个周一、周二、周三、周四、周五的10:15触发"0 15 10 15 * ?"
每月15号的10:15触发"0 15 10 L * ?"
每月的最后一天的10:15触发"0 15 10 ? * 6L"
每月最后一个周五的10:15触发"0 15 10 ? * 6L"
每月最后一个周五的10:15触发"0 15 10 ? * 6L 2002-2005"
2002年至2005年的每月最后一个周五的10:15触发"0 15 10 ? * 6#3"
每月的第三个周五的10:15触发
以上例子都是我的现实项目改过来的。。。经过测试的。。O(∩_∩)O哈哈哈~
哎。。肚子饿死了。。。。吃东西去。。。中午还没吃东西的。。。。嘿嘿~~~~~~~~
"30 * * * * ?" 每半分钟触发任务
"0 15 10 ? * 5#3" 每个月第三周的星期四的10点15分0秒触发任务
-----------------------------------------------------------------------------------------
Quartz的使用前准备:
1.引入必要的jar包:
- quartz_all_xxx.jar 或者quartz_xxx.jar
- slf4j_api_xx.jar quartz所需要的日志工具
quartz知识简单了解:
2.quartz的两种作业存储方式:
- RAMJobStore,利用内存来持久化调度程序信息
- JDBC作业存储,利用JDBC驱动和后台库中保存的调度程序信息
3.Quartz两种触发器
- simpleTrigger 适合执行简单的调度任务
- cronTrigger 使用cron表达式,调度相对复杂的任务
4.quartz调度器—将任务和触发器关联起来。
由scheduler接口体现,该接口主要定义了三个方法:
- void addJob(JobDetail jobDetail, Boolean replace)
- Date scheduleJob(JobDetail jobDetail, Trigger trigger) //使用trigger类控制该job
- Date scheduleJob(Trigger trigger) //添加触发器调度作业
在spring中使用quartz,创建quartz作业bean的两种方法:
1.使用JobDetailBean包装QuartzBean子类的实例
- 创建一个Quartz的作业bean,但是这个bean必须要继承QuartzJobBean抽象类,其中要实现一个executeInternal(JobExecutionContext ctx)方法。
2.使用MethodInvokingJobDetailFactoryBean配置方法(如下例Spring-action.xml 配置)
3.Spring-action.xml 配置内容:
<!--quartz demo test start--> <!-- 定义要定时工作bean 并将任务工程注入 --> <bean id="quarzDemo" class="com.pgw.util.QuarzDemo" > <property name="scheduler" ref="schedulerFactory" /> </bean> <!-- 将testQuarzt注入到job中 --> <bean id="testJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- targetObject 为要定时调用的工作bean --> <property name="targetObject" ref="quarzDemo" /> <!-- targetMethod 为targetObject中要触发的方法名 --> <property name="targetMethod" value="doSomething" /> </bean> <!-- 将job注入到定时触发器 --> <bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <!-- 上边定义好的job Bean注入到触发器中 --> <property name="jobDetail" ref="testJob" /> <!-- cron表达式,定义要触发的时间 --> <property name="cronExpression"> <value>0 56 10 * * ?</value> </property> </bean> <!-- 将触发器注入任务工程 --> <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" autowire="no"> <property name="triggers"> <list> <!-- 任务工程中要触发的触发器列表 --> <ref local="testTrigger" /> </list> </property> </bean> <!-- 动态填入cron表单式的界面action bean --> <bean id="quartzAction" class="com.pgw.action.QuartzAction"> <property name="quarzDemo" ref="quarzDemo"></property> </bean> <!--quartz demo test end --></beans>
QuarzDemo类
public class QuarzDemo{ private Scheduler scheduler; publicvoid doSomething() { System.out.println("Hello World !!!"); } publicvoid resetJob(String cronExpression){ try { // 运行时可通过动态注入的scheduler得到trigger, // 注意采用这种注入方式在有的项目中会有问题,如果遇到注入问题, // 可以采取在运行方法时候,获得bean来避免错误发生。 CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger("testTrigger", Scheduler.DEFAULT_GROUP); String originConExpression = trigger.getCronExpression(); // 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob if (!originConExpression.equalsIgnoreCase(cronExpression)) { trigger.setCronExpression(cronExpression); scheduler.rescheduleJob("testTrigger", Scheduler.DEFAULT_GROUP, trigger); } } catch (SchedulerException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } publicvoid setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } public Scheduler getScheduler() { returnscheduler; } }
注意:
1.lazy-init如果设置为true,这任务工程在服务器启动时不会加载。所以这里必须设置为false。
2.由于在上边的配置中定义的了default-autowire=“byName”,
Spring会自动注入quartz中的datasource bean,所以会报异常。
解决方法:在bean中关掉autowired
- quarzy实现定时任务以及和spring整合
- 整合spring实现定时任务
- Spring 和Quartz2 整合实现动态定时任务
- spring和quartz整合实现定时任务(配置文件配置方式
- SpringMVC整合Quartz实现定时任务和Spring自带Task定时任务
- SpringMVC整合Quartz实现定时任务和Spring自带Task定时任务
- SpringMVC整合Quartz实现定时任务和Spring自带Task定时任务
- Spring整合TimerTask实现定时任务调度
- Spring整合Quartz实现定时任务调度
- spring整合quartz实现定时任务调度
- Spring整合quartz实现定时任务
- Spring整合Quartz实现动态定时任务
- Spring 整合 Quartz 实现动态定时任务
- Spring整合Quartz实现定时任务调度
- Spring 整合 Quartz 实现定时任务
- Spring整合Quartz实现定时任务
- Spring整合Quartz实现定时任务调度
- Spring整合TimerTask实现定时任务调度
- 子页面获取父页面元素并进行相关的操作
- 【数据结构算法】——内部排序整理总结
- iOS之旅--封装NavigationController
- Maven搭建SpringMVC+Hibernate项目详解
- python基础教程共60课-第12课for循环
- quarzy实现定时任务以及和spring整合
- 深入理解Java:SimpleDateFormat安全的时间格式化
- 【二维数组】声明一个二维数组,为该数组随机赋值,并输出该数组
- IOS的进阶之路
- linux的 压缩与解压 命令集
- onNewIntent
- LeetCode:Isomorphic Strings
- POJ 3468 线段树区间更新
- hdoj Least Common Multiple 1019 && 2028 (n个数的最小公倍数)