最近在做后台运行Jobs的统计和监控。原本想写一个Job的基类,在基类中使用listener的方式解耦Jobs和监听的操作。
翻了翻Quartz的源码,发现Quartz本身已经有一整套完整的Listeners机制。分别在Job、Trigger、Scheduler三层都有Listener。
Quartz的Tutorial的Lesson 7 & 8提到了这些Listener接口:http://www.quartz-scheduler.org/docs/tutorial/index.html
但是Spring封装后如何使用这些Lisener,印象中Spring的文档中没有提到。回去翻了翻Spring文档,果然还是没有这方面的例子。
继续翻Spring源码。在SchedulerFactoryBean的基类SchedulerAccessor中,有如下方法
[img]http://dl.iteye.com/upload/attachment/335506/a72f56a2-cc8a-3420-b66e-bcc56c358271.jpg[/img]
换句话说,就可以在配置SchedulerFactory的时候注入这些listener。针对我的需求,我实现了一个JobListener并将其加入GlobalJobListeners。上源码:
最后补充下,Spirng版本2.6.5,Quartz版本1.6.1
翻了翻Quartz的源码,发现Quartz本身已经有一整套完整的Listeners机制。分别在Job、Trigger、Scheduler三层都有Listener。
Quartz的Tutorial的Lesson 7 & 8提到了这些Listener接口:http://www.quartz-scheduler.org/docs/tutorial/index.html
但是Spring封装后如何使用这些Lisener,印象中Spring的文档中没有提到。回去翻了翻Spring文档,果然还是没有这方面的例子。
继续翻Spring源码。在SchedulerFactoryBean的基类SchedulerAccessor中,有如下方法
[img]http://dl.iteye.com/upload/attachment/335506/a72f56a2-cc8a-3420-b66e-bcc56c358271.jpg[/img]
换句话说,就可以在配置SchedulerFactory的时候注入这些listener。针对我的需求,我实现了一个JobListener并将其加入GlobalJobListeners。上源码:
<bean id="notifyTopListener" class="com.oa.scm.app.task.listener.NotifyTopListener">
<!--
Top Path for production environment
<constructor-arg value="http://top.oa.com/"/>
-->
<constructor-arg value="http://nvwa.oa.com/~rayazhang/top_projccc/"/>
</bean>
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="globalJobListeners">
<list>
<ref bean="notifyTopListener" />
</list>
</property>
<property name="triggers">
<list>
<!--
<ref bean="checkInTrigger" />
<ref bean="workflowWacthTrigger" />
<ref bean="cronPAdjMail" />
<ref bean="cronPtraceMail" />
<ref bean="cronAlarmNotify" />
<ref bean="svnPermissionTrigger" />
<ref bean="mailTaskWacthTrigger" />
<ref bean="cronSyncOAEmployeeTask" />
<ref bean="cronInitWebOnDatabase" />
<ref bean="cronAlarmCaseScan" />
<ref bean="cronAlarmCaseRemindMail" />
<ref bean="cronAlarmCaseScan" />
<ref bean="cronAlarmCaseScan" />
<ref bean="cronAlarmTask" />
<ref bean="cronWarnRemindProcessor" />
<ref bean="cronSensetivePersonProcessor" />
-->
<!--<ref bean="cronInventoryScheduleJobAssign" />
<ref bean="cronInventoryScheduleMail" />
<ref bean="cronInventoryTaskNotifyMail" />
<ref bean="cronInventoryTaskRemindMail" />
<ref bean="cronInventoryTaskResultMail" />
<ref bean="cronInventoryTaskChangeResposebleMail" />
<ref bean="OAFlowEventTask" />
<ref bean="cronAccessLogScan" />-->
</list>
</property>
</bean>
<bean id="notifyTopListener" class="com.oa.scm.app.task.listener.NotifyTopListener">
<!--
Top Path for production environment
<constructor-arg value="http://top.oa.com/"/>
-->
<constructor-arg value="http://nvwa.oa.com/~rayazhang/top_projccc/"/>
</bean>
<bean id="scheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="globalJobListeners">
<list>
<ref bean="notifyTopListener" />
</list>
</property>
<property name="triggers">
<list>
<!--
<ref bean="checkInTrigger" />
<ref bean="workflowWacthTrigger" />
<ref bean="cronPAdjMail" />
<ref bean="cronPtraceMail" />
<ref bean="cronAlarmNotify" />
<ref bean="svnPermissionTrigger" />
<ref bean="mailTaskWacthTrigger" />
<ref bean="cronSyncOAEmployeeTask" />
<ref bean="cronInitWebOnDatabase" />
<ref bean="cronAlarmCaseScan" />
<ref bean="cronAlarmCaseRemindMail" />
<ref bean="cronAlarmCaseScan" />
<ref bean="cronAlarmCaseScan" />
<ref bean="cronAlarmTask" />
<ref bean="cronWarnRemindProcessor" />
<ref bean="cronSensetivePersonProcessor" />
-->
<!--<ref bean="cronInventoryScheduleJobAssign" />
<ref bean="cronInventoryScheduleMail" />
<ref bean="cronInventoryTaskNotifyMail" />
<ref bean="cronInventoryTaskRemindMail" />
<ref bean="cronInventoryTaskResultMail" />
<ref bean="cronInventoryTaskChangeResposebleMail" />
<ref bean="OAFlowEventTask" />
<ref bean="cronAccessLogScan" />-->
</list>
</property>
</bean>
public class NotifyTopListener implements JobListener {
private static final Logger LOGGER = Logger.getLogger(NotifyTopListener.class);
private final String topPath;
public NotifyTopListener(String topPath) {
this.topPath = topPath;
}
@Override
public String getName() {
return this.getClass().getName();
}
@Override
public void jobExecutionVetoed(JobExecutionContext jobexecutioncontext) {
//Don't care job execution vetoed
}
@Override
public void jobToBeExecuted(JobExecutionContext jobexecutioncontext) {
notifyTop(jobexecutioncontext.getJobDetail().getName(), "start");
}
@Override
public void jobWasExecuted(JobExecutionContext jobexecutioncontext,
JobExecutionException jobexecutionexception) {
String jobName = jobexecutioncontext.getJobDetail().getName();
notifyTop(jobName, jobexecutionexception == null ? "finish" : "error");
}
private void notifyTop(String jobName, String status) {
try {
URL url = new URL(buildUrlString(jobName, status));
URLConnection openConnection = url.openConnection();
openConnection.setUseCaches(false);
openConnection.getInputStream();
} catch (IOException e) {
LOGGER.error("notify top failed while job " + jobName + " " + status, e);
}
}
private String buildUrlString(String jobName, String status) {
StringBuffer sb = new StringBuffer(topPath);
sb.append("apis/job_listener.php?job=");
sb.append(jobName);
sb.append("&status=");
sb.append(status);
return sb.toString();
}
}
public class NotifyTopListener implements JobListener {
private static final Logger LOGGER = Logger.getLogger(NotifyTopListener.class);
private final String topPath;
public NotifyTopListener(String topPath) {
this.topPath = topPath;
}
@Override
public String getName() {
return this.getClass().getName();
}
@Override
public void jobExecutionVetoed(JobExecutionContext jobexecutioncontext) {
//Don't care job execution vetoed
}
@Override
public void jobToBeExecuted(JobExecutionContext jobexecutioncontext) {
notifyTop(jobexecutioncontext.getJobDetail().getName(), "start");
}
@Override
public void jobWasExecuted(JobExecutionContext jobexecutioncontext,
JobExecutionException jobexecutionexception) {
String jobName = jobexecutioncontext.getJobDetail().getName();
notifyTop(jobName, jobexecutionexception == null ? "finish" : "error");
}
private void notifyTop(String jobName, String status) {
try {
URL url = new URL(buildUrlString(jobName, status));
URLConnection openConnection = url.openConnection();
openConnection.setUseCaches(false);
openConnection.getInputStream();
} catch (IOException e) {
LOGGER.error("notify top failed while job " + jobName + " " + status, e);
}
}
private String buildUrlString(String jobName, String status) {
StringBuffer sb = new StringBuffer(topPath);
sb.append("apis/job_listener.php?job=");
sb.append(jobName);
sb.append("&status=");
sb.append(status);
return sb.toString();
}
}
最后补充下,Spirng版本2.6.5,Quartz版本1.6.1