SpringBoot中切点实现请求和返回数据的打印

1.定义切点

1.1 类上面加上下方注解

@Aspect // 定义一个切面
@Configuration //配置类

1.2 指定切点位置

 @Pointcut("execution(* com.example.demo.controller..*Controller.*(..))")
    public void excudeService() {
    }

其中execution表达式可以自行扩展.

此处表示com.example.demo.controller包及其子包中所有以Controller结尾的类中的所有方法.

简单扩展

execution(* com.example.demo.controller..Controller.(..))

  • controller后有两个点

    表示本身及其子包,改为一个点,则只表示当前包下

  • *Controller

    以Controller结尾

2.切点实现

上方定义了实现方法excudeService()

2.1 方法上加上注解

 	// 切点实现
    @Around("excudeService()")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    }

2.2 编写具体代码

写完你不用启动项目,idea就会帮你推断哪些地方会使用上.

image-20210817200359385

3.参考代码

package com.example.demo.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
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.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

/**
 * @Description: 切面实现 controller请求与返回数据的打印
 * @Class: LogRecordAspect
 * @Author: Yiang37
 * @Date: 2021/8/6 11:40
 * @Version: 1.0
 */
@Configuration
@Aspect // 定义一个切面
@Slf4j //代码直接写log.xx即可
public class LogRecordAspect {
    // 定义切点
    @Pointcut("execution(* com.example.demo.controller..*Controller.*(..))")
    public void excudeService() {
    }

    // 切点实现
    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        log.info("----------------------------------------------------");
        // 1.请求处理
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        assert servletRequestAttributes != null;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String uri = request.getRequestURI();
        // 获取请求方式
        String method = request.getMethod();
        // GET
        if ("GET".equals(method)) {
            StringBuilder stringBuilder = new StringBuilder();
            // request.getParameterMap()只能获取Get方式传入的数据
            Map<String, String[]> parameterMap = request.getParameterMap();
            for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                stringBuilder.append(entry.getKey()).append(" - ").append(Arrays.toString(entry.getValue())).append("
");
            }
            // 去掉最后一个多余的回车符
            stringBuilder.deleteCharAt(stringBuilder.length()-1);
            log.info(">> | 请求开始,URI: '{}', method: '{}', Data:
{}", uri, method, stringBuilder);
        }
        // POST
        if ("POST".equals(method)) {
            try (BufferedReader bufferedReader = new BufferedReader(request.getReader())) {
                // 每次读取一行
                StringBuilder stringBuilder = new StringBuilder();
                String str;
                while ((str = bufferedReader.readLine()) != null) {
                    stringBuilder.append(str);
                }
                // 美化下stringBuilder这个json字符串的格式
                String prettyJsonStr = JSON.toJSONString(JSONObject.parseObject(stringBuilder.toString()), SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat);
                log.info(">> | 请求开始,URI: '{}', method: '{}', Data:
{}", uri, method, prettyJsonStr);
            } catch (IOException e) {
                log.error("Post参数请求解析失败:{}", e.getMessage());
            }
        }

        // 2.返回处理
        Object result = pjp.proceed();
        log.info("<< | 请求结束,controller返回值:
" + JSON.toJSON(result));
        log.info("----------------------------------------------------");
        return result;
    }
}

4.相关pom包

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

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

<!-- fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

日志相关使用可以看我这篇文章:

Springboot中slf4j+log4j2的使用

原文地址:https://www.cnblogs.com/yang37/p/15153970.html