• springAop Schedule,注解annotation 实现任务监控


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

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

    还是那样,先让定时任务启动起来,当前我们使用的是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="当日到期的还款人发短信")
    /**
        * * <p>
        * 定时任务监控,用于方法上<br/>
        * 在新建定时任务时,在方法上写taskNo=任务编号,此时拦截器会根据编号信息,获取任务执行情况,更改任务情况,并且给任务加上异常捕获,
        * 监控任务信息。
        * </p>
        * @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、完成。。

  • 相关阅读:
    linux实现后台运行并输出日志文件
    Excel中rank函数的正确使用方法
    Shell脚本的if语句
    【Hive】CSV序列化方式
    windows10 下如何让程序被 Cortana搜索到
    【kettle & postgresql】temporary file size exceeds temp_file_limit解决办法
    【WPF & VTK】 C# 如何关闭vtkOutputWindow
    【Git】清理未做版本控制的文件
    【Hive & Spark】修复分区
    【kettle】文件分隔符
  • 原文地址:https://www.cnblogs.com/a393060727/p/7060589.html
Copyright © 2020-2023  润新知