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/

  • 相关阅读:
    准备 FRM 考试——方法、工具与教训
    930. 和相同的二元子数组 前缀和
    1906. 查询差绝对值的最小值 前缀和
    剑指 Offer 37. 序列化二叉树 二叉树 字符串
    815. 公交路线 BFS
    518. 零钱兑换 II dp 完全背包
    1049. 最后一块石头的重量 II dp
    5779. 装包裹的最小浪费空间 二分
    5778. 使二进制字符串字符交替的最少反转次数 字符串 滑动窗口
    474. 一和零 dp
  • 原文地址:https://www.cnblogs.com/hongdada/p/9100076.html
Copyright © 2011-2022 走看看