加载中…
个人资料
陈超超
陈超超
  • 博客等级:
  • 博客积分:0
  • 博客访问:230,857
  • 关注人气:37
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

通过spring实现对所有定时任务进行AOP拦截,和实现每个定时任务执行的时间从数据库动态获得

(2013-01-24 13:57:49)
标签:

方式

spring

定时任务

动态获得

aop

分类: 我的职业--SSH
通过spring实现对所有定时任务进行AOP拦截,和实现每个定时任务执行的时间从数据库动态获得,这样可以保证不需要重启容器就可以修改某个定时任务的执行时间

1.spring.xml配置AOP切面
<bean id="methodTimeAdvice" class="cn.abc.timertask.core.common.taskManager.MethodTimeAdvice">
    </bean>
<!-- 每个定时任务AOP拦截获得执行时间 -->  
<aop:config proxy-target-class="true">    
        <!--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(..))"/>    
</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.MethodInvokingJobDetailFactoryBean">
<!-- 调用的类 -->
<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.MethodInvokingJobDetailFactoryBean"> 
 <!-- 调用的类 --> 
 <property name="targetObject" ref="weatherTask" />
 <!-- 调用类中的方法 -->
 <property name="targetMethod" value="work" />
 </bean> 
 <!-- 定义触发时间 --> 
<bean id="weatherTask_cronTrigger" class="cn.abc.timertask.core.common.taskManager.InitializingCronTrigger">
 <property name="taskid" value="weatherTask"></property> 
 <property name="jobDetail" ref="weatherTask_schedulerJobDetail" />
 <property name="scheduleInfoManager" ref="scheduleInfoManager" /> 
 </bean>

<!-- 从数据库获得并动态更新所有定时任务的时间 -->
<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.MethodInvokingJobDetailFactoryBean">
<!-- 调用的类 -->
<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
    public void setScheduleInfoManager(ScheduleInfoManager scheduleInfoManager){
    System.out.println("----------------初始化"+taskid+"定时任务时间-----------------");
        this.scheduleInfoManager = scheduleInfoManager;
       
        String cronExpression = "0 0 0 */1 * ?";//所有定时任务的执行时间都初始化为一天执行一次
        try {
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>






0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有