【Exception】getReader() has already been called for this request
【Exception】getReader() has already been called for this request
一、问题描述
1、在SpringMVC的拦截器中,使用了一次 HttpServletRequest 的 getInputStream() 或 getReader() 的方法后,再次在调用,就会抛出异常:
getReader() has already been called for this request
2、最简单的触发:
@RequestMapping(value = "/rankData/mapForm")
@ResponseBody
public ResultVO mapForm(HttpServletRequest request) {
try {
BufferedReader reader = request.getReader();
String line ;
StringBuffer sb = new StringBuffer();
while((line= reader.readLine())!= null) {
sb.append(line);
}
System.out.println("resFrom :" + sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
try {
ServletInputStream inputStream = request.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,Charset.defaultCharset()));
String line ;
StringBuffer sb = new StringBuffer();
while((line= bufferedReader.readLine())!= null) {
sb.append(line);
}
System.out.println("resFrom222 :" + sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
return ResultVO.success("");
}
二、解决思路
1、创建MyHttpServletRequestWrapper 类,继承 HttpServletRequestWrapper,重写 getInputStream 和 getReader 方法
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StreamUtils;
/**
* description: 重写 MyHttpServletRequestWrapper
* @version v1.0
* @author w
* @date 2021年4月20日下午3:56:53
**/
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] requestBody = null;// 用于将流保存下来
public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() throws IOException {
// 读取 requestBody 中的数据
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
/**
* description: 提供获取requestBody的方法
*
* @return byte[]
* @version v1.0
* @author w
* @date 2021年4月20日 下午4:02:29
*/
public byte[] getRequestBody() {
return requestBody;
}
}
2、创建拦截器:实现对 HttpServletRequestWrapper类的重写
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* description: RequestBodyFilter
* @version v1.0
* @author w
* @date 2021年4月20日下午4:03:09
**/
public class RequestBodyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println(RequestBodyFilter.class.getName() + " ---->run");
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest) {
requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);
}
if (requestWrapper == null) {
chain.doFilter(request, response);
} else {
chain.doFilter(requestWrapper, response);
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
3、配置过滤器,略。
三、总结
1、经过测试,分别调用: request.getReader() 和 request.getInputStream() 方法多次,没有遇到异常信息。
2、遇到 request.getInputStream() 只能调用一次的问题,咋办呢? 重写一个HttpServletRequestWrapper 方法, 增加过滤器进行配置,即可。
参考资料: Spring Boot 添加过滤器
还没有评论,来说两句吧...