quartz 在WEB中应用小结

前一个项目曾经用到过quartz,没好好总结一下,现在的项目中又用到了,害得我又花了查了两天查资料、做测试!现在OK了,系统目前运行正常,做个小结。

1. 基本配置

官网上有quartz的所有版本,下一个,把quartz-all-*.jar(根据需要)添加到lib目录中,在classpath目录添加quartz.properties属性文件,接下来你就可以进行开发了。
这是quartz.properties的基本配置。
Java代码 复制代码
  1.   
  2. #============================================================================   
  3. # Configure Main Scheduler Properties     
  4. #============================================================================   
  5.   
  6. org.quartz.scheduler.instanceName = TestScheduler   
  7. org.quartz.scheduler.instanceId = AUTO   
  8.   
  9. #============================================================================   
  10. # Configure ThreadPool     
  11. #============================================================================   
  12.   
  13. org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool   
  14. org.quartz.threadPool.threadCount = 3  
  15. org.quartz.threadPool.threadPriority = 5  
  16.   
  17. #============================================================================   
  18. # Configure JobStore     
  19. #============================================================================   
  20.   
  21. org.quartz.jobStore.misfireThreshold = 60000  
  22.   
  23. org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore  
#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = AUTO

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore



2. web基本应用

quartz在web项目中有多种应用方式,和项目使用的其他技术也有关系。

添加一个servlet,将它配置到web.xml中:

Java代码 复制代码
  1. <servlet>   
  2.         <servlet-name>QuartzStartupServlet</servlet-name>   
  3.         <servlet-class>com.StartupServlet</servlet-class>   
  4.         <load-on-startup>1</load-on-startup>   
  5. </servlet>  
<servlet>
		<servlet-name>QuartzStartupServlet</servlet-name>
		<servlet-class>com.StartupServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
</servlet>


这样你就可以在这个servlet中,在服务器加载的时候同时加载定时任务:

Java代码 复制代码
  1. public void init(ServletConfig cfg) throws javax.servlet.ServletException   
  2.     {   
  3.         log.info("server start!");   
  4.         initScheduler(cfg);   
  5.     }   
  6.   
  7.     protected void initScheduler(ServletConfig cfg)   
  8.     {   
  9.         try  
  10.         {   
  11.             SchedulerFactory sf = new StdSchedulerFactory();   
  12.             Scheduler scheduler = sf.getScheduler();   
  13.             SimpleExample simpleExample = new SimpleExample(scheduler);   
  14.             simpleExample.run();   
  15.         } catch (Exception e)   
  16.         {   
  17.             log.error(e);   
  18.         }   
  19.     }  
public void init(ServletConfig cfg) throws javax.servlet.ServletException
	{
		log.info("server start!");
		initScheduler(cfg);
	}

	protected void initScheduler(ServletConfig cfg)
	{
		try
		{
			SchedulerFactory sf = new StdSchedulerFactory();
			Scheduler scheduler = sf.getScheduler();
			SimpleExample simpleExample = new SimpleExample(scheduler);
			simpleExample.run();
		} catch (Exception e)
		{
			log.error(e);
		}
	}


任务定义和加载在quartz的示例中有,这里不多费口舌了。

3. xml形式的任务配置

xml形式的应用,需要使用quartz的xml支持插件,只需有实现Job接口的任务就可以;这时需要在web.xml中添加默认的servlet配置:

Java代码 复制代码
  1. <servlet>   
  2.         <display-name>Quartz Initializer Servlet</display-name>   
  3.         <servlet-name>QuartzInitializer</servlet-name>   
  4.         <servlet-class>   
  5.             org.quartz.ee.servlet.QuartzInitializerServlet   
  6.         </servlet-class>   
  7.         <load-on-startup>1</load-on-startup>   
  8.     </servlet>  
<servlet>
		<display-name>Quartz Initializer Servlet</display-name>
		<servlet-name>QuartzInitializer</servlet-name>
		<servlet-class>
			org.quartz.ee.servlet.QuartzInitializerServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>


在quartz.properties中添加xml配置需要的参数:

Java代码 复制代码
  1. #============================================================================   
  2. # Configure Plugins    
  3. #============================================================================   
  4.   
  5. org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin   
  6.   
  7. org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin   
  8. org.quartz.plugin.jobInitializer.fileNames = jobs.xml   
  9. org.quartz.plugin.jobInitializer.overWriteExistingJobs = true  
  10. org.quartz.plugin.jobInitializer.failOnFileNotFound = true  
  11. org.quartz.plugin.jobInitializer.scanInterval = 10  
  12. org.quartz.plugin.jobInitializer.wrapInUserTransaction = false  
#============================================================================
# Configure Plugins 
#============================================================================

org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin

org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
org.quartz.plugin.jobInitializer.fileNames = jobs.xml
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.plugin.jobInitializer.scanInterval = 10
org.quartz.plugin.jobInitializer.wrapInUserTransaction = false

上面配置中的fileNames是指向的classpath根目录。

在xml文件中定义任务名称和触发器,例如:
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <quartz>   
  3.     <job>   
  4.         <job-detail>   
  5.             <name>dailybalance</name>   
  6.             <group>balance</group>   
  7.             <job-class>com.SimpleJob</job-class>   
  8.         </job-detail>   
  9.         <trigger>   
  10.             <cron>   
  11.                 <name>dailybalancetrigger</name>   
  12.                 <group>balance</group>   
  13.                 <job-name>dailybalance</job-name>   
  14.                 <job-group>balance</job-group>   
  15.                 <cron-expression>0/50 * * * * ?</cron-expression>   
  16.             </cron>   
  17.         </trigger>   
  18.     </job>   
  19. </quartz>  
<?xml version="1.0" encoding="UTF-8"?>
<quartz>
	<job>
		<job-detail>
			<name>dailybalance</name>
			<group>balance</group>
			<job-class>com.SimpleJob</job-class>
		</job-detail>
		<trigger>
			<cron>
				<name>dailybalancetrigger</name>
				<group>balance</group>
				<job-name>dailybalance</job-name>
				<job-group>balance</job-group>
				<cron-expression>0/50 * * * * ?</cron-expression>
			</cron>
		</trigger>
	</job>
</quartz>

这样就OK了!几种配置可以同时应用,不会冲突!

4. quartz的动态时间管理

有时需要在不停止web服务的情况下修改任务的执行时间格式,网上的资料大多是在使用spring框架支持时如何动态管理时间格式的介绍。在使用spring支持时可以,不使用spring时更加简单。

动态时间管理的关键是要共享调度管理器对象Scheduler,我们可以在最初加载任务调度的时候将它添加到servlet上下文中。
Java代码 复制代码
  1. SchedulerFactory sf = new StdSchedulerFactory();   
  2. Scheduler scheduler = sf.getScheduler();   
  3. ......   
  4. ......   
  5. cfg.getServletContext().setAttribute(SCHEDULER_KEY, scheduler);   
  6. scheduler.start();  
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
......
......
cfg.getServletContext().setAttribute(SCHEDULER_KEY, scheduler);
scheduler.start();

这样,我们就可以在需要修改时间格式的地方使用了!下面的ctt变量就是一个ServletContext对象。通过Scheduler 的getTrigger方法取到触发器,用触发器对象的getCronExpression方法可以获得时间格式。之后你可以另外创建一个同名的触发器,也可以修改现有触发器,再让调度管理器重新加载到内存就可以了!
Java代码 复制代码
  1. /**  
  2.      * reset quartz job time  
  3.      */  
  4.     public void reSetLotteryLoseBiddingTime(int lotteryType, Date date)   
  5.     {   
  6.         scheduler = (Scheduler) this.ctt.getAttribute(TIMING_WORK_SCHEDULER);   
  7.         try  
  8.         {   
  9.             String lotteryName = "";   
  10.             switch (lotteryType)   
  11.             {   
  12.             case 1://   
  13.                 lotteryName = "ssq";   
  14.                 break;   
  15.             case 2://    
  16.             {   
  17.                 lotteryName = "3D";   
  18.             }   
  19.                 break;   
  20.             case 3://    
  21.             {   
  22.                 lotteryName = "qlc";   
  23.             }   
  24.                 break;   
  25.             case 4://    
  26.             {   
  27.                 lotteryName = "23x5";   
  28.             }   
  29.                 break;   
  30.             default:   
  31.                 break;   
  32.             }   
  33.   
  34.             loseBiddingJob = scheduler.getJobDetail("loseBiddingJob_" + lotteryName, "loseBiddingGroup");   
  35.             loseBiddingTrigger = (CronTrigger) scheduler.getTrigger("loseBiddingTrigger_" + lotteryName,   
  36.                     "loseBiddingGroup");   
  37.             String time = loseBiddingTrigger.getCronExpression();   
  38.             if (!time.equals(this.timeFormat(date)))   
  39.             {   
  40.                 loseBiddingTrigger = new CronTrigger("loseBiddingTrigger_" + lotteryName, "loseBiddingGroup",   
  41.                         "loseBiddingJob_" + lotteryName, "loseBiddingGroup"this.timeFormat(date));   
  42.                 Date ft = scheduler.rescheduleJob("loseBiddingTrigger_" + lotteryName, "loseBiddingGroup",   
  43.                         loseBiddingTrigger);   
  44.                 log.info(loseBiddingJob.getFullName() + " has been scheduled to run at: " + ft   
  45.                         + " and excute based on expression: " + loseBiddingTrigger.getCronExpression());   
  46.             }   
  47.         } catch (Exception e)   
  48.         {   
  49.             log.error(e);   
  50.         }   
  51.     }  
/**
	 * reset quartz job time
	 */
	public void reSetLotteryLoseBiddingTime(int lotteryType, Date date)
	{
		scheduler = (Scheduler) this.ctt.getAttribute(TIMING_WORK_SCHEDULER);
		try
		{
			String lotteryName = "";
			switch (lotteryType)
			{
			case 1://
				lotteryName = "ssq";
				break;
			case 2:// 
			{
				lotteryName = "3D";
			}
				break;
			case 3:// 
			{
				lotteryName = "qlc";
			}
				break;
			case 4:// 
			{
				lotteryName = "23x5";
			}
				break;
			default:
				break;
			}

			loseBiddingJob = scheduler.getJobDetail("loseBiddingJob_" + lotteryName, "loseBiddingGroup");
			loseBiddingTrigger = (CronTrigger) scheduler.getTrigger("loseBiddingTrigger_" + lotteryName,
					"loseBiddingGroup");
			String time = loseBiddingTrigger.getCronExpression();
			if (!time.equals(this.timeFormat(date)))
			{
				loseBiddingTrigger = new CronTrigger("loseBiddingTrigger_" + lotteryName, "loseBiddingGroup",
						"loseBiddingJob_" + lotteryName, "loseBiddingGroup", this.timeFormat(date));
				Date ft = scheduler.rescheduleJob("loseBiddingTrigger_" + lotteryName, "loseBiddingGroup",
						loseBiddingTrigger);
				log.info(loseBiddingJob.getFullName() + " has been scheduled to run at: " + ft
						+ " and excute based on expression: " + loseBiddingTrigger.getCronExpression());
			}
		} catch (Exception e)
		{
			log.error(e);
		}
	}



5.相关问题

配置完成后,定时任务不加载执行,在日志中报错:
java.lang.NoSuchMethodError: org.apache.commons.collections.SetUtils.orderedSet(Ljava/util/Set;)Ljava/util/Set;
这个是commons-collections.jar版本过低的原因,更换个新版本的就可以了!

还有,为了防止开发人员在本地测试时,执行定时任务造成数据冲突,需要对主机服务器Ip进行判断,只有指定的服务器上才可以执行定时任务!
Java代码 复制代码
  1. public boolean compareService(String thisIp)   
  2. {   
  3.     Properties properties = this.getProperties();   
  4.     String serviceIp = "";   
  5.     try  
  6.     {   
  7.         if (properties != null)   
  8.         {   
  9.             serviceIp = properties.getProperty("timing.work.serviceIp");   
  10.             if (serviceIp != null && serviceIp.equals(thisIp))   
  11.                 return true;   
  12.         }   
  13.     } catch (Exception e)   
  14.     {   
  15.         log.error(e);   
  16.     }   
  17.     return false;   
  18. }  
public boolean compareService(String thisIp)
{
	Properties properties = this.getProperties();
	String serviceIp = "";
	try
	{
		if (properties != null)
		{
			serviceIp = properties.getProperty("timing.work.serviceIp");
			if (serviceIp != null && serviceIp.equals(thisIp))
				return true;
		}
	} catch (Exception e)
	{
		log.error(e);
	}
	return false;
}




quartz还可以对数据库操作,还有JobStore等等,以后应用到再说!哈!附带一份《quartz开发指南》!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值