一.名词简介:
Quartz是一个完全由java编写的开源作业调度框架。Spring
为创建Quartz的Scheduler、Trigger和JobDetail提供了便利的FactoryBean类,以便能够在 Spring
容器中享受注入的好处。此外Spring还提供了一些便利工具类直接将Spring中的Bean包装成合法的任务。Spring进一步降低了使用
Quartz的难度,能以更具Spring风格的方式使用Quartz。概括来说它提供了两方面的支持:
1)为Quartz的重要组件类提供更具Bean风格的扩展类;
2)提供创建Scheduler的BeanFactory类,方便在Spring环境下创建对应的组件对象,并结合Spring容器生命周期进行启动和停止的动作。
二。项目实践
情景一:集群部署,持久化,动态创建schedule配置
1.spring-schedule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<bean id="GMTZone" class="java.util.TimeZone" factory-method="getTimeZone">
<constructor-arg value="GMT"/>
</bean>
<!--业务job生成工厂,该工厂注入了scheduleManager -->
<bean id="pharmaskyJobFactory
" class="com.infowarelab.pharmasky.service.schedule.PharmaskyJobFactory
"/>
<!--schedule管理器,用于动态添加,修改,删除schedule -->
<bean id="scheduleManager" class="com.infowarelab.pharmasky.service.schedule.ScheduleManager">
<property name="scheduler" ref="scheduleFactoryBean"/>
</bean>
<!--持久化,集群schedule工厂配置信息,实际可以在classpath下附加quartz.properties定义这些属性值 -->
<bean id="scheduleFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">PharmaskyClusteredScheduler</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">25</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
<prop
key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
<prop key="org.quartz.jobStore.isClustered">true</prop>
<prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop>
</props>
</property>
<property name="triggers">
<list>
<ref local="orderConversionCronTrigger"/>
</list>
</property>
</bean>
<!--固定jobDetail, org.quartz.JobDetail类型的JobDetail必须实现指定接口方法来执行job-->
<bean id="autoOrderStatusConversionJob" class="org.quartz.JobDetail
">
<property name="jobClass">
<value>com.infowarelab.pharmasky.service.schedule.job.HisAutoOrderConversionJob</value>
</property>
<property name="name" value="PMS-SYS-JOB-HIS-ORDER-CONVERSION"/>
<property name="group" value="PMS-GROUP"/>
<property name="requestsRecovery" value="true"/>
</bean>
<!--job触发器,绑定上面的jobDetail -->
<bean id="orderConversionCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="beanName" value="PMS-SYS-JOB-HIS-ORDER-CONVERSION-Trigger"/>
<property name="jobDetail" ref="autoOrderStatusConversionJob" />
<property name="cronExpression" value="0 0/20 * * * ?" />
<property name="timeZone" ref="GMTZone"/>
</bean>
</beans>
2.ScheduleManager.java动态管理schedule工具类

ScheduleManager.java
<!-- <br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
package
com.infowarelab.pharmasky.service.schedule;

import
java.text.ParseException;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.List;

import
org.apache.commons.lang.StringUtils;
import
org.quartz.CronTrigger;
import
org.quartz.JobDetail;
import
org.quartz.Scheduler;
import
org.quartz.SchedulerException;
import
org.quartz.Trigger;

import
com.infowarelab.common.log.Log;
import
com.infowarelab.common.log.LogFactory;
import
com.infowarelab.pharmasky.util.Config;



public
class
ScheduleManager
{

private
static
final
Loglog
=
LogFactory.getLog(ScheduleManager.
class
);

private
Schedulerscheduler;


public
void
start()
throws
SchedulerException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}

if
(scheduler.isShutdown()
||
scheduler.isInStandbyMode())
{
scheduler.start();
}
}


public
void
pause()
throws
SchedulerException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}

if
(scheduler.isStarted())
{
scheduler.standby();
}
}


public
void
stop()
throws
SchedulerException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}

if
(scheduler.isStarted()
||
scheduler.isInStandbyMode())
{
scheduler.shutdown();
}
}


public
ListlistJobDetails()
throws
SchedulerException
{
ListrstList
=
new
ArrayList
<
JobDetail
>
();

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}
String[]groupNames
=
scheduler.getJobGroupNames();
log.info(
"
[INFO]thegroupsincurrentscheduleris:
"
+
groupNames.length);

for
(
int
i
=
0
;i
<
groupNames.length;i
++
)
{
String[]jobNames
=
scheduler.getJobNames(groupNames[i]);

for
(
int
j
=
0
;j
<
jobNames.length;j
++
)
{
JobDetailjobDetail
=
scheduler.getJobDetail(jobNames[j],
groupNames[i]);

if
(jobDetail
!=
null
)
{
rstList.add(jobDetail);
}
}
}
return
rstList;
}

public
JobDetailgetJobDetail(StringjobName,StringjobGroupName)

throws
SchedulerException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}
JobDetailjob
=
scheduler.getJobDetail(jobName,jobGroupName);


if
(job
==
null
)
{
log.info(
"
[INFO]noneobjectrelativethejobName:
"
+
jobName
+
"
andjobGroupName:
"
+
jobGroupName);
}
return
job;
}

public
List
<
JobDetail
>
getJobDetailByGroup(StringjobGroupName)

throws
SchedulerException
{
List
<
JobDetail
>
list
=
new
ArrayList
<
JobDetail
>
();

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}
String[]jobNames
=
scheduler.getJobNames(jobGroupName);

log.debug(
"
[DEBUG]jobNameswith/
""
+jobGroupName
+
"
/
"
asgroupName:
"
+jobNames);

for
(
int
i
=
0
;i
<
jobNames.length;i
++
)
{
JobDetailjobDetail
=
getJobDetail(jobNames[i],jobGroupName);

if
(jobDetail
!=
null
)
{
list.add(jobDetail);

}
else
{
log
.debug(
"
[DEBUG]JobDetailwith{/
""
+
jobNames[i]
+
"
/
"
,/
""
+
jobGroupName
+
"
/
"
}
asthejobNameandjobGroupNamecannotbefound
!
"
);
}
}
return
list;
}

public
boolean
addJobDetail(JobDetailjobDetail,StringcronExpress)

throws
SchedulerException,ParseException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}

if
(jobDetail
!=
null
&&
cronExpress
!=
null
)
{

Triggertrigger
=
new
CronTrigger(jobDetail.getName(),jobDetail.getGroup(),
jobDetail.getName(),jobDetail.getGroup(),cronExpress);

DatejobDate
=
scheduler.scheduleJob(jobDetail,trigger);
log
.info(
"
[INFO]jobDetail:
"
+
jobDetail.getFullName()
+
"
hasbeenaddedintothescheduler,andthefirstFiredTimeis:
"
+
jobDate);
return
(jobDate
==
null
)
?
false
:
true
;

}
else
{
log
.info(
"
[INFO]addjobDetailfailure,theparametersonjobDetailortriggerhasnullvalue!
"
);
}
return
false
;
}

public
Trigger[]getJobTrigger(StringjobName,StringjobGroupName)

throws
SchedulerException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}
return
scheduler.getTriggersOfJob(jobName,jobGroupName);
}


public
List
<
Trigger
>
listTrigger()
throws
SchedulerException
{
List
<
Trigger
>
triggerList
=
new
ArrayList
<
Trigger
>
();

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}
String[]triggerGroupNames
=
scheduler.getTriggerGroupNames();
log
.info(
"
[INFO]thetriggergroupsamountswhichisregistedwithinthesystemis:
"
+
triggerGroupNames.length);

for
(StringtriggerGroupName:triggerGroupNames)
{

if
(triggerGroupName
!=
null
)
{
String[]triggerNames
=
scheduler
.getTriggerNames(triggerGroupName);

for
(StringtriggerName:triggerNames)
{
Triggertrigger
=
scheduler.getTrigger(triggerName,
triggerGroupName);
if
(trigger
!=
null
&&
scheduler.getTriggerState(triggerName,

triggerGroupName)
==
Trigger.STATE_NORMAL)
{
triggerList.add(trigger);

}
else
{
log.info(
"
[INFO]thetrigger:
"
+
((trigger
==
null
)
?
trigger.getFullName()
:
"
null
"
)
+
"
,notexists
"
+
"
orhasthenotnormalstatus
"
);
}
}
}
}
return
triggerList;
}

public
boolean
reScheduleJob(StringjobName,StringjobGroupName,

StringcomputedStr)
throws
SchedulerException,ParseException
{

if
(scheduler
==
null
)
{
scheduler
=
getScheduler();
}

TriggernewTrigger
=
new
CronTrigger(jobName,jobGroupName,jobName,
jobGroupName,computedStr);

newTrigger.setJobName(jobName);
newTrigger.setJobGroup(jobGroupName);


DatetriggerDate
=
scheduler.rescheduleJob(jobName,jobGroupName,newTrigger);
log.info(
"
[INFO]thejob
"
+
jobName
+
"
hasbeenupdatetofiredon:
"
+
triggerDate);

return
(triggerDate
==
null
)
?
false
:
true
;
}


public
StringgenScheduleTimeStr(
byte
type,Short
scheduleTimeParams)
{
Stringpattern
=
null
;
//
variableforcronexpress

switch
(type)
{
case
1
:
//
autoordercreationjob,theparameterturnis:weekInterval,
//
weekday,hour,minute
//
"0minutehour?*weekDay/weekInterval"
pattern
=
Config
.getString(
"
schedule.cron.express.his.order.creation
"
);
log.info(
"
[INFO]partternforhisordercreationcronexpress:
"
+
pattern);

for
(
int
i
=
0
;i
<
scheduleTimeParams.length;i
++
)
{

switch
(i)
{
case
0
:
//
minute
pattern
=
StringUtils.replace(pattern,
"
minute
"
,
scheduleTimeParams[
0
].toString());
break
;
case
1
:
//
hour
pattern
=
StringUtils.replace(pattern,
"
hour
"
,
scheduleTimeParams[
1
].toString());
break
;
case
2
:
//
weekDay
pattern
=
StringUtils.replace(pattern,
"
weekDay
"
,
getWeekIdentify(scheduleTimeParams[
2
]));
break
;
case
3
:
//
weekInterval
pattern
=
StringUtils.replace(pattern,
"
weekInterval
"
,
scheduleTimeParams[
3
].toString());
break
;
default
:
break
;
}
}
break
;

case
2
:
//
hisstocksyncjob,theparameterturnis:dayInterval,hour,
//
minute
//
"0minutehour*/dayInterval*?"
pattern
=
Config.getString(
"
schedule.cron.express.his.stock.sync
"
);
log.info(
"
[INFO]partternforhisordercreationcronexpress:
"
+
pattern);

for
(
int
i
=
0
;i
<
scheduleTimeParams.length;i
++
)
{

switch
(i)
{
case
0
:
//
minute
pattern
=
StringUtils.replace(pattern,
"
minute
"
,
scheduleTimeParams[
0
].toString());
break
;
case
1
:
//
hour
pattern
=
StringUtils.replace(pattern,
"
hour
"
,
scheduleTimeParams[
1
].toString());
break
;
case
2
:
//
dayInterval
pattern
=
StringUtils.replace(pattern,
"
dayInterval
"
,
scheduleTimeParams[
2
].toString());
break
;
default
:
break
;
}
}
break
;

default
:
break
;
}

log.info(
"
[INFO]schedulejobcronexpressis:
"
+
pattern);
return
(pattern
==
null
)
?
null
:pattern.trim();
}


/***/
/**
**********************************************************************
*/

/***/
/**
helpermethodorgettersandsetters*
*/

/***/
/**
**********************************************************************
*/


/***/
/**
*gettheweekday'sidentifylike"SUN","MON"andsoon.Inthismethod
*thedata"1"equals"SUN",sothe"7"equals"SAT";
*
*
@param
short
*thenumericdataforweekday
*
@return
Stringtheweekdayidentifywithcorrectnumericdata
*/

private
StringgetWeekIdentify(
short
weekDay)
{
Stringvalue
=
null
;

switch
(weekDay)
{
case
1
:
value
=
"
SUN
"
;
break
;
case
2
:
value
=
"
MON
"
;
break
;
case
3
:
value
=
"
TUE
"
;
break
;
case
4
:
value
=
"
WED
"
;
break
;
case
5
:
value
=
"
THU
"
;
break
;
case
6
:
value
=
"
FRI
"
;
break
;
case
7
:
value
=
"
SAT
"
;
break
;
default
:
break
;
}
return
value;
}


public
SchedulergetScheduler()
{
return
scheduler;
}


public
void
setScheduler(Schedulerscheduler)
{
this
.scheduler
=
scheduler;
}
}
情景二:单机部署,固定触发规则多个schedule,不用持久化
1.spring-schedule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
<!-- Job Bean -->
<bean name="autoOrderAuditService" class="com.infowarelab.sam.service.job.AutoOrderAuditService"></bean>
<bean name="sendAuditedOrderService" class="com.infowarelab.sam.service.job.SendAuditedOrderService"></bean>
<!-- Job由于以上job bean具有相同的触发规则,所以统一集中在这个管理器执行-->
<bean id="timerJobManagerJob" class="com.infowarelab.sam.service.job.SamJobManager" autowire="no">
<property name="tasks">
<list>
<ref bean="autoOrderAuditService"/>
<ref bean="sendAuditedOrderService"/>
</list>
</property>
<property name="samBaseInfoService" ref="samBaseInfoService"></property>
</bean>
<bean id="timerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
" autowire="no">
<property name="targetObject" ref="timerJobManagerJob" />
<property name="targetMethod" value="jobExpires" />
</bean>
<bean id="timerCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" autowire="no">
<property name="jobDetail" ref="timerJobDetail" />
<property name="cronExpression">
<value>0 0/15 * * * ?</value>
</property>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="no">
<property name="triggers">
<list>
<ref bean="timerCronTrigger" />
</list>
</property>
</bean>
</beans>
参考资料:
cronExpression表达式:
http://hi.baidu.com/the_space_of_programmer/blog/item/725759f78d383e27720eec80.html (cronExpression
quartz介绍:
http://hi.baidu.com/alliance_alex/blog/item/5c998d64241173f2f73654b0.html
集群及quartz配置说明:
http://hi.baidu.com/jiangyou001/blog/item/5196d990862d5789a977a4af.html
http://gocom.primeton.com/modules/newbb/forumtopic19180_9963_40.htm
分享到:
相关推荐
1. 添加依赖:确保项目中引入了Spring和Quartz的相关库,包括`spring-context-support`和`quartz`。 2. 配置Scheduler:在Spring的配置文件中,使用`SchedulerFactoryBean`来初始化和配置Quartz Scheduler。可以...
在 "spring-quartz.zip" 文件中,开发者已经创建了一个使用 Maven 构建的项目,该项目整合了 Spring 和 Quartz,实现了定时发送邮件的功能。通过 Spring 的强大管理和配置能力,以及 Quartz 的灵活调度,我们可以...
要在Spring 3中使用Quartz,首先需要在项目中添加Quartz库的依赖。如果你使用的是Maven,可以在pom.xml文件中添加以下依赖: ```xml <groupId>org.quartz-scheduler <artifactId>quartz <version>2.3.2 ``` ...
总结起来,"spring-quartz-021"是一个学习和实践Spring与Quartz集成的实例,它展示了如何利用Spring的管理能力,配合Quartz的强大调度功能,实现基于corn表达式的定时任务。对于Java开发者来说,掌握这种集成方式能...
总结,Spring与Quartz的整合提供了灵活的定时任务解决方案。配置驱动的方式适合大型项目,对配置有较高的灵活性;注解驱动的方式则更简洁,适合小型项目。而Spring自带的定时任务功能则提供了一种轻量级的选择,无需...
本文将详细介绍如何在Spring项目中配置和使用Quartz,帮助开发者更好地理解和掌握这项技术。 #### 二、Quartz简介 Quartz是一个全面的、开放源代码的作业调度框架,它可以被应用在J2EE和J2SE应用程序中,用于处理...
总结一下,Spring结合Quartz调度器的使用主要包括以下几个步骤: 1. 引入Quartz和Spring支持的依赖。 2. 配置Spring的ApplicationContext,创建Scheduler、Job和Trigger。 3. 编写执行定时任务的服务类。 4. 根据...
《Spring与Quartz结合实现定时任务的深度解析》 ...通过分析这个项目,开发者不仅可以掌握Spring与Quartz的结合使用,还能了解到如何设计和实现一个完整的定时任务系统,这对提升企业级应用的开发能力大有裨益。
Quartz是Java领域的一款功能强大的作业调度库,而Spring通过其优秀的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)特性,将Quartz与应用程序的其他部分无缝连接,提供...
### Spring 结合 Quartz 的定时任务两种实现方法 在企业级应用开发中,定时任务是非常常见且重要的一个功能模块。...希望本文能够帮助你在项目中更好地利用 Spring 和 Quartz 完成定时任务的开发。
总结来说,Spring与Quartz的集成使得我们可以轻松地在Java应用中实现复杂的定时任务调度。通过配置Spring的`SchedulerFactoryBean`,定义`Job`和`Trigger`,并利用Spring的依赖注入机制,我们可以创建出灵活且易于...
总结,通过上述步骤,我们已经成功地使用Spring注解配置了Quartz2.2.1,实现了基于注解的任务调度。这种方式简化了配置,使得任务管理和扩展更加方便。在实际开发中,可以根据项目需求调整触发规则,实现复杂的定时...
总结起来,"spring3.0+quartz-1.6.0定时"的实现涉及到Spring框架的定时任务支持和Quartz库的结合使用,通过Spring的配置管理Quartz调度器,定义任务和触发器,最后编写具体任务逻辑的Java类。这种组合在实际项目中...
总结来说,这个资源为你提供了一个基础的Spring与Quartz集成案例,通过学习和实践,你可以掌握如何在Spring环境中利用Quartz实现高效、灵活的定时任务管理。同时,它也鼓励开发者之间的分享和交流,共同提升技术能力...
总结来说,Spring的`spring-task`适合简单定时任务,而Quartz更适合复杂场景。通过注解方式配置定时任务简洁明了,适用于快速开发;非注解方式则提供了更大的灵活性,可以满足更多定制化需求。结合提供的文档和源码...
总结,Spring和Quartz的结合为Java应用的定时任务处理提供了强大的工具,它们的集成使得任务调度更加灵活,且易于管理和维护。无论是在简单的定时任务,还是在复杂的业务场景中,都能够找到适合的解决方案。
而Spring作为一个强大的企业级应用开发框架,提供了与Quartz的集成,使得在Spring应用中使用Quartz变得更加方便。 **邮件发送**: 在示例中,邮件发送部分使用了Apache Commons Email库,这是一个Java邮件发送库,...
总结来说,Spring与Quartz的整合可以提供强大且灵活的定时任务功能。在集群环境中,通过合理配置和设计,可以实现高可用和可扩展的定时任务系统。理解并掌握这些知识点,将有助于构建高效的企业级应用。
总结来说,"Quartz+spring定时任务demo" 提供了一个集成 Quartz 与 Spring 的实例,帮助开发者快速理解和使用这种组合来创建和管理定时任务。这不仅简化了任务的编写,还充分利用了 Spring 的优点,提高了代码的可...
Spring Quartz是一款广泛使用的Java任务调度框架,用于在应用程序中安排周期性或一次性任务。Quartz集群(Cluster)是指多个Quartz实例(节点)共享相同的作业和触发器,从而实现高可用性和故障转移。本文将深入探讨...