参考文档:
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
中内容