但這樣就太囉嗦
所以改用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傳給filterBodyReaderHttpServletRequestWrapper的功能就是先讀取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