Spring Boot 接口一个 JSON 字符串用两个对象去接收,这能行吗?

Spring Boot 接口一个 JSON 字符串用两个对象去接收,这能行吗?

💡 原文中文,约17100字,阅读约需41分钟。
📝

内容提要

本文讨论了在Spring Boot中如何在一个接口中使用多个@RequestBody注解接收JSON数据。由于请求体只能读取一次,通常只能使用一个@RequestBody注解。为了解决这一问题,作者提出使用装饰者模式创建一个可重复读取的HttpServletRequest包装类,从而实现多个@RequestBody注解的使用。最后,作者强调这种设计并不推荐,主要是技术探讨。

🔎

延伸解读

为什么默认只能有一个 @RequestBody

Spring Boot 中,@RequestBody 参数由 RequestResponseBodyMethodProcessor 解析,它通过 HttpMessageConverter 从请求体的 IO 流中读取数据。IO 流只能读取一次,因此当第一个 @RequestBody 参数解析完成后,请求体已被消费,第二个参数再读取时就会失败。所以默认情况下,一个接口方法只能有一个 @RequestBody 注解,多个会报错。

可重复读取请求体的实现思路

文章通过装饰者模式增强 HttpServletRequest:在 RepeatedlyRequestWrapper 的构造方法中,一次性将请求体读入 byte 数组,然后重写 getReader 和 getInputStream,每次调用都从 byte 数组重新生成流。这样请求体就能被多次读取。再配合 RepeatableFilter,在请求为 JSON 时替换原始请求,使多个 @RequestBody 成为可能。

为什么不推荐这种设计

虽然技术上可以实现多个 @RequestBody,但作者明确表示这不是好的设计,开发中应尽量避免。原因可能包括:代码可读性差、违反单一职责、增加维护成本,且可能隐藏性能问题(如请求体较大时缓存到内存)。文章仅作技术探讨,不建议在实际项目中采用。

❓

Q&A

在Spring Boot中,@RequestBody注解可以使用几次?

通常情况下,@RequestBody注解只能使用一次,因为请求体只能读取一次。

如何在一个接口中使用多个@RequestBody注解?

可以使用装饰者模式创建一个可重复读取的HttpServletRequest包装类,从而实现多个@RequestBody注解的使用。

RepeatedlyRequestWrapper类的作用是什么?

RepeatedlyRequestWrapper类通过将请求体数据存入字节数组中,实现了对请求体的重复读取。

使用多个@RequestBody注解的设计是否推荐?

这种设计并不推荐,主要是技术探讨,开发中应尽量避免。

如何实现HttpServletRequest的重复读取?

通过重写HttpServletRequest的getReader和getInputStream方法,将请求体数据存入字节数组中,从而实现重复读取。

RepeatableFilter的作用是什么?

RepeatableFilter用于将HttpServletRequest替换为RepeatedlyRequestWrapper,以支持多个@RequestBody注解。

🏷️

标签

➡️

继续阅读