在一次业务开发中,由于需要在拦截器中对一个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;
- /**
- *
- * 从请求体中获取参数请求包装类:
- * @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()));
- }
- }