一、相关往期文章
SpringBoot+Vue实现AOP系统日志功能_aop的vue完整项目
Spring AOP (面向切面编程)原理与代理模式—实例演示_面向切面aop原理详解
二、需求分析
按照一般情况,统一接受类可以像以下的方式进行处理:


如果不想使用 @RequestBody RequestPack<RequestPackSave> requestPack 当然也可以使用AOP在controller层数据执行之前,对数据进行处理。
三、代码实现
controller层正常写就行

//该方法只对使用了@RequestBody注解的参数生效
@RestControllerAdvice
public class GlobalRequestAdvice implements RequestBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        // 此处true代表执行当前advice的业务,false代表不执行
        return true;}
    /**
     * 读取参数前执行
     *
     * @param httpInputMessage
     * @param methodParameter
     * @param type
     * @param aClass
     * @return 返回一个新的 HttpInputMessage,该消息可能包含修改后的请求体。
     * @throws IOException
     * HttpInputMessage httpInputMessage: 表示原始的 HTTP 请求消息。
     * MethodParameter methodParameter: 表示控制器方法的参数。
     * Type type: 表示方法参数的类型。
     * Class<? extends HttpMessageConverter<?>> aClass: 表示将要使用的
     * HttpMessageConverter 类型。
     */
    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
        return new HttpInputMessage() {
            @Override
            public InputStream getBody() throws IOException {
                String bodyStr = IOUtils.toString(httpInputMessage.getBody(), "utf-8");
                GlobalHttpReceive httpReceive = GsonUtil.jsonToObject(bodyStr, GlobalHttpReceive.class);
                if (httpReceive != null) {
                    Object data = httpReceive.getReqData();
                    if (data != null) {
                        return IOUtils.toInputStream(GsonUtil.objectToJson(data), "utf-8");
                    }}throw new SSError(GlobalCodeEnum.RequestFormatError);}
            @Override
            public HttpHeaders getHeaders() {
                return httpInputMessage.getHeaders();
            }};}
    /**
     * 读取参数后执行
     *
     * @param o
     * @param httpInputMessage
     * @param methodParameter
     * @param type
     * @param aClass
     * @return
     */
    @Override
    public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return o;}
    /**
     * 无请求时的处理
     *
     * @param o
     * @param httpInputMessage
     * @param methodParameter
     * @param type
     * @param aClass
     * @return
     */
    @Override
    public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return o;}
} 
四、解释说明
RequestBodyAdvice的设计初衷是为了拦截并处理那些使用了@RequestBody注解的参数。也就是说,当一个控制器方法参数被@RequestBody注解标注时,Spring 会在处理该参数时调用RequestBodyAdvice。supports方法的参数:MethodParameter methodParameter: 代表方法参数的相关信息。Type type: 代表方法参数的类型。Class<? extends HttpMessageConverter<?>> aClass: 代表将要使用的HttpMessageConverter类型。-  
始终返回
在实现true:RequestBodyAdvice接口的类中,supports方法返回true意味着对于所有进入的请求体参数,都会执行beforeBodyRead、afterBodyRead和handleEmptyBody等方法。换句话说,无论请求体的内容是什么,只要这个参数被@RequestBody注解标记,当前的RequestBodyAdvice实现就会对其进行处理。 - 当 Spring 处理某个带有 
@RequestBody注解的方法参数时,会调用supports方法。 - 由于 
supports方法始终返回true,因此所有带有@RequestBody注解的参数都会被当前的RequestBodyAdvice处理。 
return new HttpInputMessage() {
    @Override
    public InputStream getBody() throws IOException {
        String bodyStr = IOUtils.toString(httpInputMessage.getBody(), "utf-8");
        GlobalHttpReceive httpReceive = GsonUtil.jsonToObject(bodyStr, GlobalHttpReceive.class);
        if (httpReceive != null) {
            Object data = httpReceive.getReqData();
            if (data != null) {
                return IOUtils.toInputStream(GsonUtil.objectToJson(data), "utf-8");
            }
        }
        throw new SSError(GlobalCodeEnum.RequestFormatError);
    }
    @Override
    public HttpHeaders getHeaders() {
        return httpInputMessage.getHeaders();
    }
};
 


这段代码是一个全局请求处理的拦截器类,主要实现了Spring的RequestBodyAdvice接口,用于对请求的@RequestBody参数进行处理。具体功能如下:
-  
supports方法用于判断是否执行当前advice的业务逻辑,这里始终返回true,表示对所有使用了@RequestBody注解的参数进行处理。 -  
beforeBodyRead方法在读取参数前执行,首先将请求体内容转换为字符串,然后尝试将其转换为GlobalHttpReceive对象,提取其中的reqData字段。如果reqData不为空,则将其转换为JSON字符串后重新封装成InputStream返回;否则抛出SSError(GlobalCodeEnum.RequestFormatError)异常。 -  
afterBodyRead方法在读取参数后执行,这里直接返回参数对象。 -  
handleEmptyBody方法用于处理无请求体时的情况,这里也直接返回参数对象。 
        通过始终返回 true,supports 方法确保了任何带有 @RequestBody 注解的参数都会进入 RequestBodyAdvice 的处理方法中,从而实现对这些参数的统一预处理逻辑。这种设计使得开发者可以集中管理和处理所有请求体的数据,而不需要在每个控制器方法中分别编写重复的处理代码。
五、对比分析

虽然 RequestBodyAdvice 并不是严格的 AOP,但它确实体现了 AOP 的一些思想。举个例子,如果你要记录所有请求体的数据,可以这样实现:
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;
import java.lang.reflect.Type;
@ControllerAdvice
public class LoggingRequestBodyAdvice extends RequestBodyAdviceAdapter {
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        // 支持所有请求体的处理
        return true;
    }
    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 在读取请求体之后记录日志
        System.out.println("Request Body: " + body);
        return body;
    }
    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 处理空请求体的情况
        System.out.println("Request Body is empty");
        return body;
    }
}
 
  RequestBodyAdvice 并不完全属于 AOP 范畴,但它利用了类似于 AOP 的拦截机制来处理请求体的读取过程。在 Spring Boot 中,真正的 AOP 通常通过 @Aspect 注解和切点表达式来实现,用于更广泛的应用场景。而 RequestBodyAdvice 则是专门针对 HTTP 请求体处理的一种机制。












![[C++ STL] list 详解](https://img-blog.csdnimg.cn/direct/0825024dcc1f453b963c03491a097877.png)




