参考文档:
ContentCachingRequestWrapper解决入参读取
使用方法
增加拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
  import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.ContentCachingRequestWrapper;
 
 
 
  @Component @Order(1) public class RequestWrapFilter extends OncePerRequestFilter {     @Override     protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {         ContentCachingRequestWrapper wrapper =                 new ContentCachingRequestWrapper(httpServletRequest);         filterChain.doFilter(wrapper, httpServletResponse);     } }
   | 
 
注册拦截器
注册方法不赘述。例如上述代码中@Component @Order(1)会自动注册Filter
读取方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
   | import java.io.IOException; import java.nio.charset.StandardCharsets; import javax.servlet.http.HttpServletRequest;
  import com.google.common.io.ByteSource;
  import org.springframework.web.util.ContentCachingRequestWrapper;
  public class HttpBodyReader {     private HttpBodyReader() {     }
      
 
 
 
 
 
 
 
      public static String getRequestBody(HttpServletRequest request) throws IOException {         String responseBody = "";         if (request instanceof ContentCachingRequestWrapper) {             ContentCachingRequestWrapper cachingWrapper = (ContentCachingRequestWrapper) request;             byte[] buf = cachingWrapper.getContentAsByteArray();             if (buf.length > 0) {                 responseBody = ByteSource.wrap(buf)                         .asCharSource(StandardCharsets.UTF_8)                         .read();             }         }         return responseBody;     } }
   | 
 
原理
在spring框架读入输入流时会调用getInputStream()方法
wrapper重写getInputStream()方法,将流替换成ContentCachingInputStream内部类
1 2 3 4 5 6 7
   | @Override public ServletInputStream getInputStream() throws IOException {     if (this.inputStream == null) {         this.inputStream = new ContentCachingInputStream(getRequest().getInputStream());     }     return this.inputStream; }
   | 
 
ContentCachingInputStream重写了read方法,在流式读取的过程中把内容复写到外部类的cachedContent中
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | @Override public int read() throws IOException {     int ch = this.is.read();     if (ch != -1 && !this.overflow) {         if (contentCacheLimit != null && cachedContent.size() == contentCacheLimit) {             this.overflow = true;             handleContentOverflow(contentCacheLimit);         }         else {             cachedContent.write(ch);         }     }     return ch; }
   | 
 
再通过getContentAsByteArray()方法即可反复读取cachedContent中内容