美文网首页
controller层统一拦截进行日志处理

controller层统一拦截进行日志处理

作者: 霸气里尔登 | 来源:发表于2017-08-04 15:02 被阅读123次

    前言

    在项目中添加统一日志时,我们往往会用到aop进行切面处理,常用在controller层添加切面,以处理请求和返回的各项参数数据。

    使用切面进行日志处理

    下面我们就看一个例子说明基本的使用方式:

    package com.ding.test.core.aspect;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.slf4j.MDC;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    @Aspect
    @Component
    public class LogAspect {
    private final static Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
    @Pointcut("execution(* com.ding..controller.*.*(..))")
    public void printLog() {
    
    }
    /**
     * 会话ID
     */
    private final static String SESSION_TOKEN_KEY = "sessionTokenId";
    
    @Around("printLog()")
    private Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
         String token = java.util.UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
         MDC. put(SESSION_TOKEN_KEY, token);
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
    
        // 获取请求相关信息
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();
    
        // 获取调用方法相信
        Signature signature = pjp.getSignature();
        String className = signature.getDeclaringTypeName();
        String methodName = signature.getName();
        LOGGER.info("请求开始, {}#{}() URI: {}, method: {}, URL: {}, params: {}", className, methodName, uri, method, url,
                queryString);
        //result的值就是被拦截方法的返回值
        try {
            //proceed方法是调用实际所拦截的controller中的方法,这里的result为调用方法后的返回值
            Object result = pjp.proceed();
            long endTime = System.currentTimeMillis();
            //定义请求结束时的返回数据,包括调用时间、返回值结果等
            LOGGER.info("请求结束, {}#{}(), URI: {}, method: {}, URL: {}, time: {}ms, result: {} ", className, methodName,
                    uri, method, url, (endTime - startTime), result);
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            LOGGER.error("请求出错, {}#{}(), URI: {}, method: {}, URL: {}, time: {}ms", className, methodName, uri, method,
                    url, (endTime - startTime), e);
            throw e;
        }finally {
            MDC. remove(SESSION_TOKEN_KEY);
        }
     }
    }
    

    本来spring就自带一套aop实现,我们直接使用此实现即可,本来使用aop还需要定义一些xml文件,但由于我们使用的是spring-boot框架,这一步就省略掉了。也就是说,在spring-boot中,我们可以直接使用aop而不需要任何的配置。

    这里我们分析一下上面的示例代码:

    @Aspect:描述一个切面类,定义切面类的时候需要打上这个注解

    @Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

    @PointCut("execution(* com.ding..controller..(..))"):定义切点,括号内的为拦截的路径,这里指目录下的controller中所以方法

    这里定义切点的方法为printLog(),在进行前置通知、后置通知、环绕通知的时候,就可以根据这个方法进行拦截。这里我们用到了环绕通知的方式: @Around("printLog()"),定义后,在进行controller中方法调用时就会先调用这里的doAround方法。方法中的含义在注释中已经写清楚了,可以打断点再看每段代码的具体含义。

    后记

    本文通过一个案例讲解了一下使用切面进行日志处理的功能,重点在于配置切点、环绕通知、方法调用。这些成功后就按照自己需求进行日志内容的输出了。

    ============================================================
    输出倒逼输入,作为技术人员教是最好的学习方法,我是一名爱思考、爱学习、涉猎广泛想搞事情的程序员。

    坚持就是娱乐,因为惊喜更重要
    ============================================================

    相关文章

      网友评论

          本文标题:controller层统一拦截进行日志处理

          本文链接:https://www.haomeiwen.com/subject/ycnvlxtx.html