You need to enable JavaScript to run this app. Spring如何在Controller方法外部访问@RequestBody绑定的对象
优惠活动
大模型
产品
解决方案
定价
更多

Spring如何在Controller方法外部访问@RequestBody绑定的对象

存在完全符合要求的实现方案,基于Spring MVC原生的RequestBodyAdvice即可实现,不需要修改任何原有Controller代码,也不会产生重复反序列化的开销。

实现原理

Spring MVC在处理@RequestBody参数时,会先通过消息转换器将请求流反序列化为目标对象,在将对象注入到Controller方法参数之前,会触发所有匹配的RequestBodyAdvice实现的回调。你可以在这个回调节点直接拿到已经完成反序列化的对象,执行校验或存储逻辑,完全符合你的需求。

具体实现步骤
  • 自定义类实现RequestBodyAdvice接口,添加@ControllerAdvice注解使其全局生效,也可通过注解的属性限定生效范围,避免拦截非目标接口
  • 重写supports方法,设置拦截规则,只有匹配你需要校验的目标类型的请求才会进入后续处理,降低性能损耗
  • 重写afterBodyRead方法,直接获取反序列化完成的@RequestBody对象,执行你的校验逻辑,如果后续业务组件需要使用该对象,可将其存入当前请求的HttpServletRequest属性中,同请求链路下的组件可直接读取使用
参考代码
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Type;

// 可通过basePackages、annotations等属性限定生效范围
@ControllerAdvice(basePackages = "com.your.business.controller")
public class TargetTypeValidationAdvice implements RequestBodyAdvice {
    // 自定义Request属性存储的key,避免和其他属性冲突
    private static final String VALIDATED_BODY_KEY = "VALIDATED_REQUEST_BODY";

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, 
                            Class<? extends HttpMessageConverter<?>> converterType) {
        // 仅拦截你需要校验的目标类型,比如你要校验的是OrderDTO类,这里直接匹配类型即可
        return targetType.getTypeName().equals(OrderDTO.class.getName());
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, 
                                Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 直接拿到已经反序列化完成的对象,无需重复反序列化
        OrderDTO targetBody = (OrderDTO) body;
        // 执行你的校验逻辑,校验不通过可直接抛出业务异常终止请求
        validateTargetBody(targetBody);
        // 若后续业务组件需要使用该对象,存入当前请求的属性中
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        request.setAttribute(VALIDATED_BODY_KEY, targetBody);
        return body;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, 
                                           Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        return inputMessage;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, 
                                  Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    private void validateTargetBody(OrderDTO body) {
        // 你的自定义校验逻辑实现
    }
}
方案说明
  • 完全不侵入原有Controller代码,所有逻辑独立在Advice中实现
  • 复用Spring原生的反序列化结果,没有额外的反序列化开销
  • 支持灵活调整生效范围,可针对特定包、特定注解、特定类型的请求生效,不会影响其他业务接口
  • 同请求链路下的其他业务组件可直接通过HttpServletRequest.getAttribute(VALIDATED_BODY_KEY)获取已经校验完成的对象,无需重复获取或校验
  • 若使用的是Spring WebFlux响应式框架,替换为响应式版本的RequestBodyAdvice实现即可,核心逻辑一致

内容的提问来源于stack exchange,提问作者regisxp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 02:54:02