zoukankan      html  css  js  c++  java
  • SpringBoot 全局统一记录日志

    1.记录日志

    使用aop来记录controller中的请求返回日志

    pom.xml引入:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    在完成了引入AOP依赖包后,一般来说并不需要去做其他配置。也许在Spring中使用过注解配置方式的人会问是否需要在程序主类中增加@EnableAspectJAutoProxy来启用,实际并不需要。

    可以看下面关于AOP的默认配置属性,其中spring.aop.auto属性默认是开启的,也就是说只要引入了AOP依赖后,默认已经增加了@EnableAspectJAutoProxy。

    # AOP
    spring.aop.auto=true # Add @EnableAspectJAutoProxy.
    spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false).

    1.使用Around

    @Aspect
    @Component
    public class ControllerAspect {
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        /**
         * Controller aspect.
         */
        @Pointcut("execution(* com.shitou.huishi.service..*.*(..))")
        public void controllerAspect() {
        }
    
        /**
         * Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
         * <p>
         * 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice
         *
         * @param pjp
         *            the pjp
         * @return object
         * @throws Throwable
         *             the throwable
         */
        @Around(value = "controllerAspect()")
        public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            HttpServletRequest request = sra.getRequest();
    
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
            logger.info("REQUEST ARGS : " + JSON.toJSONString(pjp.getArgs()));
    
            long startTime = System.currentTimeMillis();
            try {
                Object response = pjp.proceed();
                // 2.打印出参,返回结果
                long endTime = System.currentTimeMillis();
                // 3.出参打印
                logger.info("RESPONSE:{}", response != null ? JSON.toJSONString(response) : "");
                logger.info("SPEND TIME : {}ms", (endTime - startTime));
                return response;
            } catch (AuthException e) {
                logger.info("RESPONSE ERROR:{}", e.getMsg());
                throw e;
            } catch (HuishiApiException e) {
                logger.info("RESPONSE ERROR:{}", e.getMsg());
                throw e;
            } catch (MethodArgumentNotValidException e) {
                logger.info("RESPONSE ERROR:{}", e.getMessage());
                throw e;
            } catch (Throwable e) {
                logger.error("RESPONSE ERROR:{}", Arrays.toString(e.getStackTrace()));
                throw e;
            } finally {
                long endTime = System.currentTimeMillis();
                logger.error("SPEND TIME : {}ms", (endTime - startTime));
            }
        }
    }

    2.使用Before,AfterReturning处理:

    import java.util.Arrays;
    import javax.servlet.http.HttpServletRequest;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    /**
     * Created by qhong on 2018/5/28 14:25
     **/
    @Aspect
    @Component
    public class LogAspect {
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        ThreadLocal<Long> startTime = new ThreadLocal<>();
    
        @Pointcut("execution(public * com.shitou.huishi.service.*.*(..))")
        public void logAspect(){}
    
        @Before("logAspect()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            startTime.set(System.currentTimeMillis());
    
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            // 记录下请求内容
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    
        }
    
        @AfterReturning(returning = "ret", pointcut = "logAspect()")
        public void doAfterReturning(Object ret) throws Throwable {
            // 处理完请求,返回内容
            logger.info("RESPONSE : " + ret);
            logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
        }
    }

    两种方式计算出来的时间,参数,返回体是一样的。

    完善版本:

    import com.alibaba.fastjson.JSON;
    import com.shitou.huishi.contract.datacontract.exception.AuthException;
    import com.shitou.huishi.contract.datacontract.exception.HuishiApiException;
    import java.util.Arrays;
    import javax.servlet.http.HttpServletRequest;
    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.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    /**
     * 类描述: 日志拦截器,打印controller层的入参和出参<br> 创建时间: 2016/7/29 0029 <br>
     *
     * @author 李恒
     */
    @Aspect
    @Component
    public class ControllerAspect {
    
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        /**
         * Controller aspect.
         */
        @Pointcut("execution(* com.shitou.huishi.service..*.*(..))")
        public void controllerAspect() {
        }
    
        /**
         * Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
         * <p>
         * 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice
         *
         * @param pjp the pjp
         * @return object
         * @throws Throwable the throwable
         */
        @Around(value = "controllerAspect()")
        public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            //防止不是http请求的方法,例如:scheduled
            if (ra == null || sra == null) {
                return pjp.proceed();
            }
            HttpServletRequest request = sra.getRequest();
    
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
            logger.info("REQUEST ARGS : " + JSON.toJSONString(pjp.getArgs()));
    
            long startTime = System.currentTimeMillis();
            try {
                Object response = pjp.proceed();
                // 3.出参打印
                logger.info("RESPONSE:{}", response != null ? JSON.toJSONString(response) : "");
                return response;
            } catch (Throwable e) {
                if (e instanceof AuthException) {
                    logger.info("RESPONSE ERROR:{}", ((AuthException) e).getMsg());
                } else if (e instanceof HuishiApiException) {
                    logger.info("RESPONSE ERROR:{}", ((HuishiApiException) e).getMsg());
                } else if (e instanceof MethodArgumentNotValidException) {
                    logger.info("RESPONSE ERROR:{}", e.getMessage());
                } else {
                    logger.error("RESPONSE ERROR:{}", Arrays.toString(e.getStackTrace()));
                }
                throw e;
            } finally {
                long endTime = System.currentTimeMillis();
                logger.info("SPEND TIME : {}ms", (endTime - startTime));
            }
        }
    }

    http://blog.didispace.com/springbootaoplog/

    http://blog.didispace.com/springbootexception/

  • 相关阅读:
    A. Vanya and Table
    B. Chris and Magic Square
    A. Bus to Udayland
    关于cout输出精度问题
    1087 1 10 100 1000
    1080 两个数的平方和
    CODE[VS] 1842 递归第一次
    CODE[VS] 1501 二叉树最大宽度和高度
    少年中国说
    CODE[VS] 1475 m进制转十进制
  • 原文地址:https://www.cnblogs.com/hongdada/p/9100076.html
Copyright © 2011-2022 走看看