但這樣就太囉嗦
所以改用filter來處理這件事情
但由於request body只能被讀取一次的特性
所以filter要針對request動點手腳
第10行將HttpServletRequest包裝成BodyReaderHttpServletRequestWrapper傳給filter
- @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;
- }
- }
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