通过spring实现对所有定时任务进行AOP拦截,和实现每个定时任务执行的时间从数据库动态获得
(2013-01-24 13:57:49)
标签:
方式spring定时任务动态获得aop |
分类: 我的职业--SSH |
通过spring实现对所有定时任务进行AOP拦截,和实现每个定时任务执行的时间从数据库动态获得,这样可以保证不需要重启容器就可以修改某个定时任务的执行时间
1.spring.xml配置AOP切面
</bean>
<!--Spring
2.0 可以用 AspectJ 的语法定义 Pointcut,这里拦截 指定
包中的所有方法 -->
<aop:advisor
id="methodTimeLog" advice-ref="methodTimeAdvice"
pointcut="execution(*
cn.abc.timertask.biz.*.*.*Task.work(..))
or
execution(*
cn.abc.timertask.biz.*.*.*Servlet.work(..))"/>
<!-- 调用的类
-->
<property
name="targetObject" ref="weatherTask" />
<!-- 调用类中的方法
-->
<property
name="targetMethod" value="work" />
</bean>
<!-- 定义触发时间
-->
<property
name="taskid"
value="weatherTask"></property>
<property
name="jobDetail" ref="weatherTask_schedulerJobDetail"
/>
<property
name="scheduleInfoManager" ref="scheduleInfoManager"
/>
</bean>
public void
setScheduleInfoManager(ScheduleInfoManager
scheduleInfoManager){
System.out.println("----------------初始化"+taskid+"定时任务时间-----------------");
this.scheduleInfoManager =
scheduleInfoManager;
String cronExpression = "0 0 0 */1 *
?";//所有定时任务的执行时间都初始化为一天执行一次
try {
}
<bean id="methodTimeAdvice"
class="cn.abc.timertask.core.common.taskManager.MethodTimeAdvice">
<!-- 每个定时任务AOP拦截获得执行时间 -->
<aop:config
proxy-target-class="true">
</aop:config>
<!--
以下配置了两个bean,即两个定时任务
-->
<!-- 配置一个bean
-->
<bean id="huPaymentTask"
class="cn.abc.timertask.biz.fight.huPayment.HuPaymentTask">
</bean>
<!-- 定义调用对象和调用对象的方法 -->
<bean
id="huPaymentTask_schedulerJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailF actoryBean">
<!-- 调用的类 -->
<property name="targetObject"
ref="huPaymentTask" />
<!-- 调用类中的方法 -->
<property name="targetMethod" value="work"
/>
</bean>
<!-- 定义触发时间 -->
<bean id="huPaymentTask_cronTrigger"
class="cn.abc.timertask.core.common.taskManager.InitializingCronTrigger">
<property name="taskid"
value="huPaymentTask"></property>
<property name="jobDetail"
ref="huPaymentTask_schedulerJobDetail" />
<property name="scheduleInfoManager"
ref="scheduleInfoManager" />
</bean>
<!--
配置另一个bean -->
<bean id="weatherTask"
class="cn.abc.timertask.biz.fight.weather.WeatherTask">
</bean> <!--
定义调用对象和调用对象的方法 -->
<bean id="weatherTask_schedulerJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailF actoryBean">
<bean id="weatherTask_cronTrigger"
class="cn.abc.timertask.core.common.taskManager.InitializingCronTrigger">
<!-- 从数据库获得并动态更新所有定时任务的时间
-->
<bean id="schedulerFactoryTask"
class="cn.abc.timertask.core.common.taskManager.SchedulerFactoryTask">
<property name="schedulerFactory"
ref="schedulerFactory"/>
<property name="scheduleInfoManager"
ref="scheduleInfoManager"/>
</bean>
<!-- 定义调用对象和调用对象的方法 -->
<bean
id="schedulerFactoryTask_schedulerJobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailF actoryBean">
<!-- 调用的类 -->
<property name="targetObject"
ref="schedulerFactoryTask" />
<!-- 调用类中的方法 -->
<property name="targetMethod" value="work"
/>
</bean>
<!-- 定义触发时间 -->
<bean
id="schedulerFactoryTask_cronTrigger"
class="cn.abc.timertask.core.common.taskManager.InitializingCronTrigger">
<property name="taskid"
value="schedulerFactoryTask"></property>
<property name="jobDetail"
ref="schedulerFactoryTask_schedulerJobDetail"
/>
<property name="scheduleInfoManager"
ref="scheduleInfoManager" />
</bean>
<!-- 数据库操作类 -->
<bean id="scheduleInfoManager"
class="cn.abc.timertask.core.common.taskManager.ScheduleInfoManager"/>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序
-->
<bean id="schedulerFactory" lazy-init="false"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref local="huPaymentTask_cronTrigger"
/>
<ref local="weatherTask_cronTrigger"
/>
</list>
</property>
</bean>
2.HuPaymentTask.java
一个定时任务类,WeatherTask.java与这个类似,就不写了
package
cn.abc.timertask.biz.fight.huPayment;
public class HuPaymentTask {
public void work() {
System.out.println("这里写这个定时任务需要执行的操作代码");
}
}
3.MethodTimeAdvice.java
切面类,其中加入了将拦截的内容加入到数据库的代码,如果不需要可以相应删掉
package cn.abc.timertask.core.common.taskManager;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.ThrowsAdvice;
import
cn.abc.timertask.core.common.taskManager.po.TaskDetail;
public class MethodTimeAdvice implements MethodInterceptor
{
protected final Log log =
LogFactory.getLog(MethodTimeAdvice.class);
public Object invoke(MethodInvocation invocation) {
Object[] object = invocation.getArguments();
ScheduleInfoManager scheduleInfoManager = new
ScheduleInfoManager();//这个类封装了对数据库的增删改查操作
TaskDetail taskDetail = new TaskDetail();//这是一个实体
// 用 commons-lang 提供的 StopWatch 计时,Spring 也提供了一个
StopWatch
StopWatch clock = new StopWatch();
clock.start(); // 计时开始
String beforeTime = new SimpleDateFormat("yyyy-MM-dd
HH:mm:ss:SSS").format(new Date());
System.out.println("启动时间:"+ beforeTime);
taskDetail.setTask_detail_startdate(beforeTime);
Object result = null;
try {
result = invocation.proceed();
System.out.println(result);
taskDetail.setTask_detail_isexception("0");
} catch (Exception e) {
// TODO: handle exception
System.out.println("捕获的异常:"+e.getMessage());
String exceptionTime = new SimpleDateFormat("yyyy-MM-dd
HH:mm:ss:SSS").format(new Date());
taskDetail.setTask_detail_isexception("1");
taskDetail.setTask_detail_exceptiondesc(e.getMessage());
taskDetail.setTask_detail_executedate(exceptionTime);
}finally{
clock.stop(); // 切面结束
String endTime = new SimpleDateFormat("yyyy-MM-dd
HH:mm:ss:SSS").format(new Date());
System.out.println("结束时间:"+ endTime);
taskDetail.setTask_detail_enddate(endTime);
// 方法参数类型,转换成简单类型
Class[] params =
invocation.getMethod().getParameterTypes();
String[] simpleParams = new String[params.length];
for (int i = 0; i < params.length; i++) {
simpleParams[i] = params[i].getSimpleName();
}
System.out.println("结束时间:" + clock.getTime() + " ms");
taskDetail.setTask_detail_executedate(clock.getTime() + "
ms");
System.out.println("每次执行时间:" + clock.getTime() + " ms");
System.out.println("操作类(包名+类名+方法名+(参数)): ["
+ invocation.getThis().getClass().getName() + "."
+ invocation.getMethod().getName() + "("
+ StringUtils.join(simpleParams, ",") + ")] ");
System.out.println(result);
//这里将拦截的数据插入的数据库
scheduleInfoManager.insertTaskDetail(taskDetail);
return result;
}
}
}
4.InitializingCronTrigger.java//每个定时器调用的初始化时间类
package cn.abc.timertask.core.common.taskManager;
import java.io.Serializable;
import java.text.ParseException;
import
org.springframework.scheduling.quartz.CronTriggerBean;
import
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
public class InitializingCronTrigger extends CronTriggerBean
implements Serializable {
private ScheduleInfoManager scheduleInfoManager;
private String taskid;
public void setTaskid(String taskid) {
this.taskid = taskid;
}
public ScheduleInfoManager getScheduleInfoManager() {
return scheduleInfoManager;
}
public String getTaskid() {
return taskid;
}
// 设值注入,通过setter方法传入被调用者的实例scheduleInfoManager
setCronexpression_r(cronExpression);
if(taskid.equals("schedulerFactoryTask")){//如果调用的是总定时器
setCronexpression_r("0/10 * * * *
?");//设置总定时器每个10分钟更新一次所有的定时器的时间
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// ②
}
5.SchedulerFactoryTask.java
为所有定时器更新相应的执行时间
package cn.abc.timertask.core.common.taskManager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import
org.springframework.scheduling.quartz.CronTriggerBean;
public class SchedulerFactoryTask {
private Scheduler schedulerFactory;
private ScheduleInfoManager scheduleInfoManager;
// 设值注入,通过setter方法传入被调用者的实例scheduler
public void setSchedulerFactory(Scheduler schedulerFactory)
{
this.schedulerFactory = schedulerFactory;
}
public ScheduleInfoManager getScheduleInfoManager() {
return scheduleInfoManager;
}
public void setScheduleInfoManager(ScheduleInfoManager
scheduleInfoManager) {
this.scheduleInfoManager = scheduleInfoManager;
}
public void work(){
try {
ApplicationContext context = new
ClassPathXmlApplicationContext("spring-triggers.xml");//spring-triggers.xml如下,其中是一个所有定时器名字的集合
List quartzList =
(ArrayList)context.getBean("quartzList");
for(int i = 0;i
CronTriggerBean trigger = (CronTriggerBean)
schedulerFactory.getTrigger(quartzList.get(i),
Scheduler.DEFAULT_GROUP);
String dbCronExpression = "" ;
dbCronExpression =
scheduleInfoManager.getCronExpressionFromDB(quartzList.get(i).split("_")[0]);
//System.out.println(trigger+"+++++");
String originConExpression =
trigger.getCronexpression_r();
//System.out.println(trigger+"===="+originConExpression);
//
判断从DB中取得的任务时间(dbCronExpression)和现在的quartz线程中的任务时间(originConExpression)是否相等
// 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob
if(!originConExpression.equalsIgnoreCase(dbCronExpression)){
trigger.setCronexpression_r(dbCronExpression);
schedulerFactory.rescheduleJob(quartzList.get(i),
Scheduler.DEFAULT_GROUP, trigger);
}
}
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
6.spring-triggers.xml
这是一个所有定时任务名字的LIST,当然你也可以从数据库获得或其他方式定义
<?xml version="1.0"
encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 所有定时任务的id名字集合List -->
<bean id="quartzList"
class="java.util.ArrayList">
<constructor-arg>
<list>
<value>huPaymentTask_cronTrigger</value>
<value>weatherTask_cronTrigger</value>
</list>
</constructor-arg>
</bean>
</beans>

加载中…