Springboot使用AOP记录请求日志和返回数据

Spring给我们的提供了强大的AOP功能;什么是AOP?AOP为Aspect Oriented Programming的缩写,意为:面向切面编程;我们可以使用它来做一些统一动作,这里我将使用它来记录我们的Controller层接口的请求日志和返回数据。

代码清单:
pom.xml

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

记录日志核心代码:LogAspectj.java

@Slf4j
@Aspect
@Component
public class LogAspectj {
    
    

    /**
     * 切入点
     */
    @Pointcut("execution(public * cn.tugos.logaop.demo.controller.*Controller.*(..))")
    public void logAspect() {
    
    

    }

    /**
     * 环绕操作
     * 记录请求日志
     */
    @Around("logAspect()")
    public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
    
    

        // 获取请求参数
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        // 记录执行时间
        long startTime = System.currentTimeMillis();
        //处理请求
        Object result = joinPoint.proceed();

        //记录日志
        try {
    
    
            LogVO logVo = LogVO.builder()
                    //请求ip
                    .ip(HttpUtils.getIpAddress(request))
                    //请求路径
                    .url(request.getRequestURL().toString())
                    //处理的类
                    .classMethod(String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()))
                    //处理的方法类型
                    .httpMethod(request.getMethod())
                    //请求参数
                    .requestParams(getRequestParam(joinPoint))
                    //返回结果
                    .result(result)
                    //耗时
                    .timeCost(System.currentTimeMillis() - startTime).build();
            log.info("请求参数和处理信息 : {}", JSONUtil.toJsonStr(logVo));
        } catch (Exception e) {
    
    
            log.warn("记录请求日志失败:", e);
        }
        return result;
    }

    /**
     * 获取请求参数
     */
    private Object[] getRequestParam(ProceedingJoinPoint joinPoint) {
    
    
        Object[] args = joinPoint.getArgs();
        Object[] arguments = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
    
    
            if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
    
    
                //ServletRequest,ServletResponse,MultipartFile不能序列化
                continue;
            }
            arguments[i] = args[i];
        }
        return arguments;
    }


}

记录日志的VO:LogVO.java

@Data
@Builder
public class LogVO {
    
    

    // ip
    private String ip;

    // url
    private String url;

    // 请求方式 GET POST
    private String httpMethod;

    // 类方法
    private String classMethod;

    // 请求参数
    private Object requestParams;

    // 返回参数
    private Object result;

    // 接口耗时
    private Long timeCost;

}

获取ip地址工具:HttpUtils.java

public class HttpUtils {
    
    


    private static final String SIGN = ",";

    private static final String STR_UNKNOWN = "unknown";

    /**
     * 获取请求ip
     */
    public static String getIpAddress(HttpServletRequest request) {
    
    
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || STR_UNKNOWN.equalsIgnoreCase(ip)) {
    
    
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || STR_UNKNOWN.equalsIgnoreCase(ip)) {
    
    
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || STR_UNKNOWN.equalsIgnoreCase(ip)) {
    
    
            ip = request.getRemoteAddr();
        }
        if (ip == null || ip.length() == 0 || STR_UNKNOWN.equalsIgnoreCase(ip)) {
    
    
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || STR_UNKNOWN.equalsIgnoreCase(ip)) {
    
    
            ip = request.getHeader("X-Real-IP");
        }
        if (ip.contains(SIGN)) {
    
    
            return ip.split(SIGN)[0];
        } else {
    
    
            return ip;
        }
    }


}

使用postman发送http测试请求
在这里插入图片描述
控制台打印日志

2021-02-18 14:29:47.324  INFO 59827 --- [nio-8080-exec-1] cn.tugos.logaop.demo.aspectj.LogAspectj  : 请求参数和处理信息 : {
    
    "classMethod":"cn.tugos.logaop.demo.controller.TestController.test","ip":"0:0:0:0:0:0:0:1","requestParams":[{
    
    "sex":"man","name":"qinming","age":"18"}],"httpMethod":"POST","url":"http://localhost:8080/test","result":{
    
    "requestParam":{
    
    "sex":"man","name":"qinming","age":"18"}},"timeCost":7}

GitHub源码:https://github.com/qinming99/tugos-demo

猜你喜欢

转载自blog.csdn.net/qq_33505611/article/details/113846654