Springboot踩坑-request body重复读问题

背景

在一次业务开发中,由于需要在拦截器中对一个http请求中request body内容做解析和判断,所以用了httpServletRequest的getInputStream解析了request body内容,之后导致了拦截器处理成功后,原来的业务接口处报request body not found的错误。

原理

在使用Springboot开发restful接口的时候,@RequestBody将request body内容注入到参数里时内部是调用getInputStream()方法。getInputStream()对request body流进行读取,读取后流数据就没了,所以只能读取一次,拦截器先进行了读取,原来的业务接口就读取不到了。

解决方案

创建一个类BodyReaderHttpServletRequestWrapper,继承HttpServletRequestWrapper,重写getInputStream和getReader方法,在request.getInputStream之后保存请求体,之后业务代码就可以重复读request body了。

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StreamUtils;
/**
*
* 从请求体中获取参数请求包装类:<br>
* @author nick
* @version 5.0 since 2018年9月5日
*/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper{
private byte[] requestBody = null;//用于将流保存下来
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
@Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要确定@RequestBody是用于绑定HTTP请求的HTTP请求主体(body)到方法参数或方法返回值上的注解。当使用@RequestBody注解时,SpringBoot会自动将处理程序方法参数绑定到HTTP请求主体中的JSON对象上。 如果@RequestBody的请求主体JSON为null,则有可能是请求的Content-Type与数据类型不匹配。例如,请求的Content-Type为application/json,但是请求体的格式不是JSON,或者请求体中的JSON格式存在问题,导致SpringBoot无法将其转换为对象。 解决这个问题需要按照以下步骤进行: 1. 确认请求主体是否为null,这可以通过在方法中打印日志或使用调试器进行调试来实现。 2. 确认请求头中的Content-Type是否与请求主体的数据格式相匹配。 3. 确认请求体中的JSON格式是否正确,可以使用JSON 校验工具确认。 4. 如果以上步骤均无法解决问题,则可以考虑使用自定义JSON反序列化器。 在自定义反序列化器中,可以通过添加注解@JsonDeserialize(using = CustomDeserializer.class)来指定自定义反序列化器。这样,在接收到JSON请求主体时,SpringBoot会使用自定义反序列化器将JSON数据转换为Java对象。如果仍然无法解决问题,可以查看SpringBoot的日志文件,查找相关错误信息进行解决。 总之,当SpringBoot的@RequestBody接收JSON为null时,需要仔细检查请求格式是否正确并考虑使用自定义反序列化器解决问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值