SpringBoot 记录日志

使用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

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

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.slf4j.MDC;
import org.springframework.stereotype.Component;

import com.shitou.common.logging.LayoutLog;
 
@Aspect
@Component
public class ControllerAspect {
    private Logger logger = null;

    /**
     * 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 {
        // 1.入参打印
        String className = pjp.getSignature().getDeclaringTypeName();
        MDC.put(LayoutLog.TRACE_ID, UUID.randomUUID().toString());
        logger = LoggerFactory.getLogger(className);
        List<String> methodParams = new ArrayList<>();

        if (pjp.getArgs().length > 0) {
            for (Object o : pjp.getArgs()) {
                if (o == null) {
                    continue;
                }
                methodParams.add(o.toString());
            }
        }
        logger.info("request:{}", methodParams.toString());

        long startTime = System.currentTimeMillis();
        try {
            Object response = pjp.proceed();
            // 2.打印出参,返回结果
            long endTime = System.currentTimeMillis();
            // 3.出参打印
            logger.info("reponse:cost={},message={}", endTime - startTime, response != null ? response.toString() : "");
            return response;
        } catch (Throwable e) {
            long endTime = System.currentTimeMillis();
            logger.error("reponse:cost={}ms", endTime - startTime, e);
            throw e;
        }
    }

}

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()));
    }
}

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

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

猜你喜欢

转载自www.cnblogs.com/hongdada/p/9100076.html