但這樣就太囉嗦
所以改用filter來處理這件事情
但由於request body只能被讀取一次的特性
所以filter要針對request動點手腳
@WebFilter( filterName="testFilter", urlPatterns={"/testRest"} ) public class SpringRequestBodyFilter extends OncePerRequestFilter{ @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { BodyReaderHttpServletRequestWrapper requestWrapper = new BodyReaderHttpServletRequestWrapper(request); System.out.println("body: " + requestWrapper.getBody()); filterChain.doFilter(requestWrapper, response); } } public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper{ private final String body; public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); try(BufferedReader bufferedReader = request.getReader()){ body = request.getReader().lines().collect(Collectors.joining()); } } @Override public ServletInputStream getInputStream() throws IOException { return new DelegatingServletInputStream(new ByteArrayInputStream(body.getBytes())); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(this.getInputStream())); } public String getBody() { return this.body; } }第10行將HttpServletRequest包裝成BodyReaderHttpServletRequestWrapper傳給filter
BodyReaderHttpServletRequestWrapper的功能就是先讀取request body並存到body欄位中
由於前面提到過request body只能讀取一次的特性
所以要重新建立inputStream和reader
若有用到inputStream或reader時才不會出現Stream closed的錯誤
第29行這邊我用org.springframework.mock.web.DelegatingServletInputStream
這個是用spring test的(要自己實作ServletInputStream也可以,但已有寫好的沒有不拿來用的理由)
完整程式可參考https://github.com/softmenlouis/springBoot-filter.git