Logic I have to implement is logging all requests with body served to DB.
So I decided to use: afterCompletion
method of HandlerInterceptor
This is quite an old thread but for the sake of people who looking for a way to get RequestBody
and ResponseBody
from Interceptor. Here is how I got it working.
RequestBody
, can simply use IOUtils:
String requestBody= IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
ResponseBody
, I had to used HttpServletResponseCopier:
ServletLoggingFilter.HttpServletResponseCopier copier = (ServletLoggingFilter.HttpServletResponseCopier) response;
String responseBody = new String(copier.getCopy());
Here's the relevant statement from javadoc for HandlerInterceptor javadoc.
Callback after completion of request processing, that is, after rendering the view. Will be called on any outcome of handler execution, thus allows for proper resource cleanup.
HandlerIntercepter Javadoc
You cannot access the request body (as an InputStream) because the request was already read. If you need access to request parameters, you could do so using the request object by calling - request.getParameter("parameterName");
You cannot access the response body because the response is already rendered. That means the response is already committed to the outputstream.
You can extend RequestBodyAdviceAdapter
and implement the method afterBodyRead
:
@ControllerAdvice
public MyRequestBodyAdviceAdapter extends RequestBodyAdviceAdapter {
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
// write body -your input dto- to logs or database or whatever
return body;
}
}
The RequestBodyAdvice comes in pre setp the request chain before the HandlerInterceptor
. it is exactly after the http request inputstream is converted to your object.
You can get the request body from HTTPServlet request inside HandlerInterceptorAdapter methods using the method:
request.getInputStream();
If you want it to use with scanner you can assign the scanner as follows:
Scanner scanner = new Scanner(request.getInputStream(), "UTF-8");
Then you can use the required data from the scanner using some manipulation or scanner tricks. Or else you can assign it to a string also using Apache Commons IO:
String requestStr = IOUtils.toString(request.getInputStream());
You may use ResponseBodyAdvice
available since Spring 4.1, with which you could intercept the response body before the body is written to the client.
Here is an example: https://sdqali.in/blog/2016/06/08/filtering-responses-in-spring-mvc/
As far as I know, RequestBody
and ResponseBody
can be read only once. So you should not read them in an Interceptor
.
Here's some explanation.