springAop Schedule,注解annotation 实现任务监控
阅读原文时间:2023年07月10日阅读:1

我们有很多定时任务在任务工程中执行,但是如果我们不加以监控,很有可能定时任务死掉或者卡住我们都不知道。

所以需要做一个任务监控。监控任务当前执行的状态。

还是那样,先让定时任务启动起来,当前我们使用的是spring提供的schedule执行定时任务。注意,这个默认情况下是单线执行,就是说你有很多定时任务,你的时间执行很频繁,他只会给你排队执行,不会到时间立马执行。如果想要配置多个定时任务同时执行,那么只需要在你任务标签上加上@Async。一般情况下。不是忒紧急的,不需要加。加上后,你就需要给你的方法调用的数据做好异步同步控制了。具体调用,可参考前一篇文章。

ok,废话不多说,开始弄代码。

1、spring配置加上以下配置,实现任务调度与切面生效。

<!-- 切面开关 -->  
<aop:aspectj-autoproxy />  
<!-- 定时器开关 -->  
<task:annotation-driven />

2、任务信息实现:

/\*\*  
 \* 提醒当天到期还款的还款人发短信  
 \*/  
@MyTask(taskNo="smsNotifyRepaymenterToday", taskDesc="当日到期的还款人发短信")  
@Scheduled(cron = "${SmsTaskExecutor.smsNotifyRepaymenterToday}")  
public void smsNotifyRepaymenterToday() {  
    String message = StatusContants.TASK\_INFO\_SMS\_NOTIFY\_REPAYMENTER\_TODAY.getName();  
    String taskNo = StatusContants.TASK\_INFO\_SMS\_NOTIFY\_REPAYMENTER\_TODAY.getIndex();  
    if (!taskService.taskDo(taskNo)){return ;}  
    try{  
        taskService.taskUpdate(taskNo, StatusContants.SYSTEM\_TABLE\_STATUS\_1.getIndex());

        logger.info(message + ControllerContants.MESSAGE\_START);  
        // 计算发送时间范围  
        String notifyDateStr = dictionaryVoService.findDeductDate(); // 会计日期当天  
        String deductDateStart = notifyDateStr;  
        String deductDateEnd = notifyDateStr;  
        // 发送  
        phoneMsgService.notifyRepaymenterTodayBySms(deductDateStart, deductDateEnd);  
        logger.info(message + ControllerContants.MESSAGE\_END);  
    }catch (Exception e) {  
        logger.error(message+"异常", e);  
        exceptionInfoService.insert(message+"异常", StatusContants.LOG\_TYPE\_EXCPETION.getIndex(), MyStringUtils.getExceptionDetail(e), getClass().getName()+".smsNotifyRepaymenter");  
    }finally{  
        taskService.taskUpdate(taskNo, StatusContants.SYSTEM\_TABLE\_STATUS\_0.getIndex());  
    }  
}

3、注解标签实现:

@MyTask(taskNo="smsNotifyRepaymenterToday", taskDesc="当日到期的还款人发短信")

/**
* *

* 定时任务监控,用于方法上
* 在新建定时任务时,在方法上写taskNo=任务编号,此时拦截器会根据编号信息,获取任务执行情况,更改任务情况,并且给任务加上异常捕获, * 监控任务信息。 *


* @author chenweixian 陈惟鲜
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTask {

String taskNo();

String taskDesc();  

}

4、监控切面的实现。

package com.chenweixian.task.aop;

import java.math.BigDecimal;
import java.util.Date;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.opensymphony.oscache.util.StringUtil;

/**Spring的定时任务推送监控
*
* @author chenweixian
*
*/
@Aspect
@Order(1) // 排序
@Component
public class ScheduleMonitoringInterceptor {
private Logger logger = Logger.getLogger(getClass());

@Autowired  
private ActiveMqUtil activeMqUtil;

@Async  
@Pointcut("@annotation(org.springframework.scheduling.annotation.Scheduled)")  // 用于拦截标签  
private void anyMethod(){}//定义一个切入点  

/\*\*  
 \*  
 \* @Title:doAround  
 \* @Description: 环绕触发  
 \* @author 陈惟鲜  
 \* @date 2014年11月3日 下午1:58:45  
 \* @param point  
 \* @return  
 \* @throws Throwable  
 \*/  
@Around("anyMethod() && @annotation(myTask)")  
public Object doAround(ProceedingJoinPoint point, MyTask myTask) throws Throwable {  
    Date startTime = MyDateUtil.getCurrentDateTime();// 开始时间

    // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行  
    Object result = point.proceed();// result的值就是被拦截方法的返回值  

    Date endTime = MyDateUtil.getCurrentDateTime();// 结束时间  
    try{  
    this.writeLog(point, myTask, startTime, endTime);  
    }catch(Exception e){  
        logger.info("记录监控日志异常。。");  
    }

    return result;  
}  

/\*\*\*记录日志\*/  
private void writeLog(JoinPoint point, MyTask myTask, Date startTime, Date endTime){  
    String taskdesc = StatusContants.getName(StatusTypeContants.TYPE\_ID\_TASK\_INFO, myTask.taskNo());  
    if (StringUtil.isEmpty(taskdesc)){  
        taskdesc = "";  
    }

    ProcedureMonitor procedureMonitor = new ProcedureMonitor();  
    procedureMonitor.setAutoId(UUIDUtils.generateUUID64());  
    procedureMonitor.setIpAddress(MyStringUtils.getIpString());// 机器IP  
    procedureMonitor.setStartTime(startTime);// 开始执行时间  
    procedureMonitor.setEndTime(endTime);// 结束执行时间  
    procedureMonitor.setConsumeTimes(new BigDecimal(endTime.getTime()-startTime.getTime()));// 总耗时时间  
    procedureMonitor.setExceptionFlag(StatusContants.SYSTEM\_TABLE\_STATUS\_0.getIndex());// 是否异常  
    procedureMonitor.setTaskNo(myTask.taskNo()); // 任务编号  
    procedureMonitor.setTaskName(myTask.taskDesc()); // 任务编号对应名称  
    procedureMonitor.setRemark("【"+point.getSignature().getDeclaringTypeName()+"."+point.getSignature().getName()+"】"+taskdesc); // 所在的类.方法  
    procedureMonitor.setBusinessType(StatusContants.PROCEDURE\_MONITOR\_TASK.getIndex()); // 监控类型  
    // 发送mq消息  
    activeMqUtil.sendMq(ActivityMqContants.TASK\_PROCEDURE\_MONITOR, JSONObject.fromObject(procedureMonitor).toString());  
}  

}

5、完成。。