HttpServetRequest读取body只能一次的问题
HTTP请求中的是字符串数据:
1 //字符串读取 2 3 void charReader(HttpServletRequest request) { 4 BufferedReader br = request.getReader(); 5 String str, wholeStr = ""; 6 while((str = br.readLine()) != null){ 7 wholeStr += str; 8 } 9 System.out.println(wholeStr); 10 } 11 //二进制读取 12 13 void binaryReader(HttpServletRequest request) { 14 int len = request.getContentLength(); 15 ServletInputStream iii = request.getInputStream(); 16 byte[] buffer = new byte[len]; 17 iii.read(buffer, 0, len); 18 }
注意:
request.getInputStream(); request.getReader(); 和request.getParameter("key");
这三个函数中任何一个函数执行一次后(可正常读取body数据),之后再执行就无效了。
解决方法: 包装HttpServletRequest对象,缓存body数据,再次读取的时候将缓存的值写出
1 package com.nd.sdp.formatastic.common.interceptor; 2 3 import javax.servlet.ServletInputStream; 4 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpServletRequestWrapper; 6 import java.io.*; 7 8 /** 9 * @author weihainan. 10 * @since 0.1 created on 2017/2/23. 11 */ 12 public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper { 13 14 private final String body; 15 16 public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { 17 super(request); 18 StringBuilder stringBuilder = new StringBuilder(); 19 BufferedReader bufferedReader = null; 20 try { 21 InputStream inputStream = request.getInputStream(); 22 if (inputStream != null) { 23 bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 24 char[] charBuffer = new char[128]; 25 int bytesRead = -1; 26 while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { 27 stringBuilder.append(charBuffer, 0, bytesRead); 28 } 29 } else { 30 stringBuilder.append(""); 31 } 32 } catch (IOException ex) { 33 throw ex; 34 } finally { 35 if (bufferedReader != null) { 36 try { 37 bufferedReader.close(); 38 } catch (IOException ex) { 39 throw ex; 40 } 41 } 42 } 43 body = stringBuilder.toString(); 44 } 45 46 @Override 47 public ServletInputStream getInputStream() throws IOException { 48 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); 49 ServletInputStream servletInputStream = new ServletInputStream() { 50 public int read() throws IOException { 51 return byteArrayInputStream.read(); 52 } 53 }; 54 return servletInputStream; 55 } 56 57 @Override 58 public BufferedReader getReader() throws IOException { 59 return new BufferedReader(new InputStreamReader(this.getInputStream())); 60 } 61 62 public String getBody() { 63 return this.body; 64 } 65 }
使用Filter替换HttpServletRequest对象
1 package com.nd.sdp.formatastic.common.interceptor; 2 3 import javax.servlet.*; 4 import javax.servlet.annotation.WebFilter; 5 import javax.servlet.http.HttpServletRequest; 6 import java.io.IOException; 7 8 /** 9 * @author weihainan. 10 * @since 0.1 created on 2017/2/23. 11 */ 12 @WebFilter(filterName = "httpServletRequestWrapperFilter", urlPatterns = "/*") 13 public class HttpServletRequestWrapperFilter implements Filter { 14 15 @Override 16 public void init(FilterConfig filterConfig) throws ServletException { 17 18 } 19 20 @Override 21 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 22 throws IOException, ServletException { 23 24 ServletRequest requestWrapper = null; 25 if (request instanceof HttpServletRequest) { 26 requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request); 27 } 28 if (null == requestWrapper) { 29 chain.doFilter(request, response); 30 } else { 31 chain.doFilter(requestWrapper, response); 32 } 33 34 } 35 36 @Override 37 public void destroy() { 38 39 } 40 }
不积跬步无以至千里