【Exception】getReader() has already been called for this request

浅浅的花香味﹌ 2023-01-18 13:20 189阅读 0赞

【Exception】getReader() has already been called for this request

一、问题描述

1、在SpringMVC的拦截器中,使用了一次 HttpServletRequest 的 getInputStream() 或 getReader() 的方法后,再次在调用,就会抛出异常:

  1. getReader() has already been called for this request

2、最简单的触发:

  1. @RequestMapping(value = "/rankData/mapForm")
  2. @ResponseBody
  3. public ResultVO mapForm(HttpServletRequest request) {
  4. try {
  5. BufferedReader reader = request.getReader();
  6. String line ;
  7. StringBuffer sb = new StringBuffer();
  8. while((line= reader.readLine())!= null) {
  9. sb.append(line);
  10. }
  11. System.out.println("resFrom :" + sb.toString());
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15. try {
  16. ServletInputStream inputStream = request.getInputStream();
  17. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,Charset.defaultCharset()));
  18. String line ;
  19. StringBuffer sb = new StringBuffer();
  20. while((line= bufferedReader.readLine())!= null) {
  21. sb.append(line);
  22. }
  23. System.out.println("resFrom222 :" + sb.toString());
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. return ResultVO.success("");
  28. }

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0hhSGFfU2ly_size_16_color_FFFFFF_t_70

二、解决思路

1、创建MyHttpServletRequestWrapper 类,继承 HttpServletRequestWrapper,重写 getInputStream 和 getReader 方法

  1. import java.io.BufferedReader;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import javax.servlet.ServletInputStream;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletRequestWrapper;
  8. import org.springframework.util.StreamUtils;
  9. /**
  10. * description: 重写 MyHttpServletRequestWrapper
  11. * @version v1.0
  12. * @author w
  13. * @date 2021年4月20日下午3:56:53
  14. **/
  15. public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
  16. private byte[] requestBody = null;// 用于将流保存下来
  17. public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
  18. super(request);
  19. requestBody = StreamUtils.copyToByteArray(request.getInputStream());
  20. }
  21. @Override
  22. public ServletInputStream getInputStream() throws IOException {
  23. // 读取 requestBody 中的数据
  24. final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);
  25. return new ServletInputStream() {
  26. @Override
  27. public int read() throws IOException {
  28. return byteArrayInputStream.read();
  29. }
  30. };
  31. }
  32. @Override
  33. public BufferedReader getReader() throws IOException {
  34. return new BufferedReader(new InputStreamReader(getInputStream()));
  35. }
  36. /**
  37. * description: 提供获取requestBody的方法
  38. *
  39. * @return byte[]
  40. * @version v1.0
  41. * @author w
  42. * @date 2021年4月20日 下午4:02:29
  43. */
  44. public byte[] getRequestBody() {
  45. return requestBody;
  46. }
  47. }

2、创建拦截器:实现对 HttpServletRequestWrapper类的重写

  1. import java.io.IOException;
  2. import javax.servlet.Filter;
  3. import javax.servlet.FilterChain;
  4. import javax.servlet.FilterConfig;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.ServletRequest;
  7. import javax.servlet.ServletResponse;
  8. import javax.servlet.http.HttpServletRequest;
  9. /**
  10. * description: RequestBodyFilter
  11. * @version v1.0
  12. * @author w
  13. * @date 2021年4月20日下午4:03:09
  14. **/
  15. public class RequestBodyFilter implements Filter {
  16. @Override
  17. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  18. throws IOException, ServletException {
  19. System.out.println(RequestBodyFilter.class.getName() + " ---->run");
  20. ServletRequest requestWrapper = null;
  21. if (request instanceof HttpServletRequest) {
  22. requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) request);
  23. }
  24. if (requestWrapper == null) {
  25. chain.doFilter(request, response);
  26. } else {
  27. chain.doFilter(requestWrapper, response);
  28. }
  29. }
  30. @Override
  31. public void destroy() {
  32. }
  33. @Override
  34. public void init(FilterConfig arg0) throws ServletException {
  35. }
  36. }

3、配置过滤器,略。

三、总结

1、经过测试,分别调用: request.getReader() 和 request.getInputStream() 方法多次,没有遇到异常信息。

2、遇到 request.getInputStream() 只能调用一次的问题,咋办呢? 重写一个HttpServletRequestWrapper 方法, 增加过滤器进行配置,即可。

参考资料: Spring Boot 添加过滤器

发表评论

表情:
评论列表 (有 0 条评论,189人围观)

还没有评论,来说两句吧...

相关阅读