SpringBoot 使用 AOP 打印请求参数和响应结果

添加依赖:

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

AOP 代码:

package com.gtcom.api.aspect;

import com.alibaba.fastjson.JSON;
import com.gtcom.constant.Constants;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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.aspectj.lang.reflect.CodeSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Aspect
@Component
public class LogAspect {

    @Pointcut("execution(* com.gtcom.api.controller..*.*(..))")
    public void pointCut() {
    }

    @Pointcut("execution(* com.gtcom.api.exception..*.*(..))")
    public void exceptionPointCut() {
    }

    @Before(value = "pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(servletRequestAttributes)) {
            return;
        }
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String ip = request.getRemoteAddr();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        log.info("[请求接口] - {} : {} : {}", ip, method, uri);
        if (log.isDebugEnabled()) {
            Object[] parameterValues = joinPoint.getArgs();
            int parameterValuesLength = parameterValues.length;
            if (parameterValuesLength == Constants.ZERO) {
                log.debug("[请求参数] - 无");
                return;
            }
            Signature signature = joinPoint.getSignature();
            if (Objects.isNull(signature)) {
                return;
            }
            String[] parameterNames = ((CodeSignature) signature).getParameterNames();
            if (Objects.isNull(parameterNames) || parameterNames.length != parameterValuesLength) {
                return;
            }
            Map<String, Object> params = new HashMap<>(Constants.TWO);
            for (int i = Constants.ZERO; i < parameterNames.length; i++) {
                params.put(parameterNames[i], parameterValues[i]);
            }
            log.debug("[请求参数] - {}", JSON.toJSONString(params));
        }
    }

    @AfterReturning(returning = "result", pointcut = "pointCut() || exceptionPointCut()")
    public void doAfterReturning(Object result) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(servletRequestAttributes)) {
            return;
        }
        HttpServletResponse response = servletRequestAttributes.getResponse();
        if (Objects.isNull(response)) {
            return;
        }
        int status = response.getStatus();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        log.info("[响应结果] - {} : {} : {}", status, method, uri);
        if (log.isDebugEnabled()) {
            log.debug("[响应内容] - {}", JSON.toJSONString(result));
        }
    }
}

打印日志:

2021-11-10 19:18:49.762 - INFO [b79971ff62ee43dd8470a4be9e602f61] 11828 --- [nio-8082-exec-1] com.gtcom.api.aspect.LogAspect           : [请求接口] - 0:0:0:0:0:0:0:1 : GET : /api/test
2021-11-10 19:18:49.763 -DEBUG [b79971ff62ee43dd8470a4be9e602f61] 11828 --- [nio-8082-exec-1] com.gtcom.api.aspect.LogAspect           : [请求参数] - 无
2021-11-10 19:18:49.767 - INFO [b79971ff62ee43dd8470a4be9e602f61] 11828 --- [nio-8082-exec-1] com.gtcom.api.controller.TestController  : =================测试接口================
2021-11-10 19:18:49.768 - INFO [b79971ff62ee43dd8470a4be9e602f61] 11828 --- [nio-8082-exec-1] com.gtcom.api.aspect.LogAspect           : [响应结果] - 200 : GET : /api/test
2021-11-10 19:18:49.845 -DEBUG [b79971ff62ee43dd8470a4be9e602f61] 11828 --- [nio-8082-exec-1] com.gtcom.api.aspect.LogAspect           : [响应内容] - {"code":20000,"message":"成功"}

这里添加了简单的 MDC:

server.servlet.context-path=/api
logging.pattern.console=%clr(%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{trace_id}]) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}
package com.gtcom.api.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * MDC拦截器
 *
 * @author wangbo
 * @date 2021/10/27
 */
@Slf4j
@Component
public class MdcInterceptor implements HandlerInterceptor {

    private final static String TRACE_ID = "trace_id";

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
        MDC.put(TRACE_ID, UUID.randomUUID().toString().replace("-", ""));
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) throws Exception {
        MDC.remove(TRACE_ID);
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
package com.gtcom.api.config;

import com.gtcom.api.interceptor.MdcInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * WebMvc配置
 *
 * @author wangbo
 * @date 2021/10/27
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final MdcInterceptor mdcInterceptor;

    public WebMvcConfig(MdcInterceptor mdcInterceptor) {
        this.mdcInterceptor = mdcInterceptor;
    }

    /**
     * 注册拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(mdcInterceptor);
    }
}
上一篇:SQL注入中information_schema的作用


下一篇:SQL注入中information_schema的作用