该错误的原因是HttpServletRequest的getInputStream()和getReader()只能调用一次,【getReader()底层调用了getInputStream()】。@RequestBody也是流的形式读取,流读取一次就没了。
这种场景一般出现在拦截器中读取了流,并且接口使用了@RequestBody注解的,就会导致重复读取流,抛出这个异常。
解决方法:
因为过滤器是优先于拦截器执行的,所以我们可以写一个过滤器,在过滤器里面把流的数据copy一份出来,放入自定义的Wrapper对象,然后把这个wrapper对象当做request往下传递(wrapper和request可以强转),这样在拦截器中拿到的就是我们copy出来的流,就可以反复读取了,如
过滤器:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request = new AuthRequestWrapper(request);
filterChain.doFilter(request,response);
}
AuthRequestWrapper:
@Slf4j
public class AuthRequestWrapper extends HttpServletRequestWrapper {
private String body;
public AuthRequestWrapper(HttpServletRequest request) {
super(request);
try(BufferedReader reader = request.getReader()){
body= reader.lines().collect(Collectors.joining());
}catch (Exception e){
log.error("!!-- read request from requestbody error",e);
}
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletIns = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return byteArrayIns.read();
}
};
return servletIns;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
后续拦截器使用:
if (request instanceof AuthRequestWrapper){
return ((AuthRequestWrapper)request).getBody();
}
标签:body,already,return,request,Override,getReader,public
From: https://www.cnblogs.com/yyfyy/p/17151175.html