欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring aop拦截springmvc的controller请求方法,添加日志和统计方法执行时间

程序员文章站 2022-05-08 17:41:39
...

前言

系统最近莫名挂了三次,查看log日志没找到原因,因为只有少数功能日志输出,大部分功能都没记录日志。打算通过spring aop来给springmvc的controller层的方法加日志,进入方法,方法执行完都记录日志,同时记录方法执行的耗时。日志输出级别为debug,通过log4j的分级别输出日志到不同的文件,下面记录下aop拦截的步骤。

1.applicationContext.xml中的配置

<!--开启注解-->
<context:annotation-config />

<!-- 使用annotation 自动注册bean,并保证@Required,@Autowired的属性被注入 -->
<context:component-scan base-package="com.***">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
 </context:component-scan>

<!-- 开启自动切面代理 -->
<aop:aspectj-autoproxy />
2.aspect类的编写 

@Before 进入方法打印带包路径的方法名和当前时间

@After 方法执行完打印带包路径的方法名和当前时间

@Around 大于常量的毫秒数,打印方法执行时间

@Aspect
@Component
public class LogInterceptor {
    private final Logger logger = Logger.getLogger(LogInterceptor.class);

    // 一分钟,即1000ms
    private static final long ONE_MINUTE = 1000;

    @Pointcut("execution(public * com.sully..controller..*.*(..))")
    public void myMethod(){};

    /**
     *  进入方法后打印日志
     * @param joinPoint
     */
    @Before("myMethod()")
    public void before(JoinPoint joinPoint) {
        logger.debug(this.getMethodName(joinPoint)+" start "+ DateUtil.getDateTime(new Date()));
    }

    /**
     * 方法结束打印日志
     * @param joinPoint
     */
    @After("myMethod()")
    public void after(JoinPoint joinPoint) {
        logger.debug(this.getMethodName(joinPoint)+" after"+ DateUtil.getDateTime(new Date()));
    }


    @Around("execution(* com.sully..controller..*.*(..))")
    public Object processLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 定义返回对象、得到方法需要的参数
        Object obj = null;
        Object[] args = joinPoint.getArgs();
        long startTime = System.currentTimeMillis();

        try {
            obj = joinPoint.proceed(args);
        } catch (Throwable e) {
            logger.error("统计某方法执行耗时环绕通知出错", e);
        }

        // 获取执行的方法名
        long endTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();

        // 打印耗时的信息
        this.printExecTime(methodName, startTime, endTime);

        return obj;
    }

    /**
     * 打印方法执行耗时的信息,如果超过了一定的时间,才打印
     * @param methodName
     * @param startTime
     * @param endTime
     */
    private void printExecTime(String methodName, long startTime, long endTime) {
        long diffTime = endTime - startTime;
        if (diffTime > ONE_MINUTE) {
            logger.debug( methodName + " 方法执行耗时:" + diffTime + " ms");
        }
    }

    /**
     * 获取方法名(类的详细包路径)
     * @param joinPoint
     * @return
     */
    private String getMethodName(JoinPoint joinPoint){
        return joinPoint.getSignature().getDeclaringTypeName() +
                "." + joinPoint.getSignature().getName();
    }

    /**
     * AfterReturning  拦截执行
     */
    @AfterReturning("execution(public * com.sully.finance..controller..*.*(..))")
    public void AfterReturning() {
        logger.debug("method AfterReturning");
    }

    /**
     *  AfterThrowing 拦截执行
     */
    @AfterThrowing("execution(public * com.sully.finance..controller..*.*(..))")
    public void AfterThrowing() {
        logger.debug("method AfterThrowing");
    }
}

3.步骤2中的日志打印都是debug级别,分级别输出日志就好