解决request.getParameter() 、 request.getInputStream()和request.getReader()只能使用一次的问题

来源:互联网 发布:js prototype 阮一峰 编辑:程序博客网 时间:2024/05/18 03:33
问题:在使用SpringMVC拦截器获取POST请求中的JSON信息的时候,使用request.getReader()方法获取JSON信息后,POST请求就不往下走了,
 
原因
1. 一个Reader对象在被读取完成后,将无法被再次读取,始终返回-1;
2. POST也是一种流,所以使用Reader方法后,POST请求返回true也不往下走了

解决方案:使用HttpServletRequestWrapper来包装HttpServletRequest,在BodyReaderHttpServletRequestWrapper中初始化读取request的Reader数据,以byte[]形式缓存在其中,然后在Filter中将request转换为包装过的request;代码如下:
public class HttpServletRequestReplacedFilter implements Filter {      @Override      public void destroy() {        }        @Override      public void doFilter(ServletRequest request, ServletResponse response,              FilterChain chain) throws IOException, ServletException {            ServletRequest requestWrapper = null;          if (request instanceof HttpServletRequest) {              HttpServletRequest httpServletRequest = (HttpServletRequest) request;              System.out.println(httpServletRequest.getContentType());            System.out.println(httpServletRequest.getContextPath());            System.out.println(httpServletRequest.getRemoteHost());            System.out.println(httpServletRequest.getMethod());            if ("POST".equals(httpServletRequest.getMethod().toUpperCase())                      ) {              //&& httpServletRequest.getContentType().equalsIgnoreCase(             // "application/json")                requestWrapper = new BodyReaderHttpServletRequestWrapper(                          (HttpServletRequest) request);              }          }            if (requestWrapper == null) {              chain.doFilter(request, response);          } else {              chain.doFilter(requestWrapper, response);           }      }        @Override      public void init(FilterConfig arg0) throws ServletException {        }    }  
public class BodyReaderHttpServletRequestWrapper extends          HttpServletRequestWrapper {            private final byte[] body;        public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {          super(request);          Enumeration e = request.getHeaderNames()   ;             while(e.hasMoreElements()){                 String name = (String) e.nextElement();                 String value = request.getHeader(name);                              }            body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));      }        @Override      public BufferedReader getReader() throws IOException {          return new BufferedReader(new InputStreamReader(getInputStream()));      }        @Override      public ServletInputStream getInputStream() throws IOException {            final ByteArrayInputStream bais = new ByteArrayInputStream(body);            return new ServletInputStream() {              @Override              public int read() throws IOException {                  return bais.read();              }          };      }        @Override      public String getHeader(String name) {          return super.getHeader(name);      }        @Override      public Enumeration<String> getHeaderNames() {          return super.getHeaderNames();      }        @Override      public Enumeration<String> getHeaders(String name) {          return super.getHeaders(name);      }        }
public class HttpHelper {      /**      * 获取请求Body      *      * @param request      * @return      */      public static String getBodyString(ServletRequest request) {          StringBuilder sb = new StringBuilder();          InputStream inputStream = null;          BufferedReader reader = null;          try {              inputStream = request.getInputStream();              reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));              String line = "";              while ((line = reader.readLine()) != null) {                  sb.append(line);              }          } catch (IOException e) {              e.printStackTrace();          } finally {              if (inputStream != null) {                  try {                      inputStream.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }              if (reader != null) {                  try {                      reader.close();                  } catch (IOException e) {                      e.printStackTrace();                  }              }          }          return sb.toString();      }  }  
web.xml配置文件
<filter>      <filter-name>HttpServletRequestReplacedFilter</filter-name>      <filter-class>com.deppon.dpap.module.syncserver.util.HttpServletRequestReplacedFilter</filter-class>  <!--     <init-param>   --><!--         <param-name>encoding</param-name>   --><!--         <param-value>utf-8</param-value>   --><!--     </init-param>   --></filter>  <filter-mapping>      <filter-name>HttpServletRequestReplacedFilter</filter-name>      <url-pattern>/*</url-pattern>  </filter-mapping>  <!--     <filter-mapping>   --><!--         <filter-name>CORS</filter-name>   --><!--         <url-pattern>/*</url-pattern>   --><!--    </filter-mapping> -->


这样运行的时候就会先走Filter再走springmvc的拦截器了,就可以多次读取了

1 0