Наконец-то я нашел способ справиться с этим с помощью пружинной загрузки Filter
путем переопределения HttpServletResponseWrapper
. так вот мой код (класс, который переопределяет HttpServletResponseWrapper
, чтобы изменить поток вывода ответа по умолчанию на мой пользовательский ServletOutputStream
):
public class HttpServletResponseCopier extends HttpServletResponseWrapper {
private ServletOutputStreamCopier copier;
private ServletOutputStream outputStream;
private PrintWriter writer;
/**
* @param response
*/
public HttpServletResponseCopier(HttpServletResponse response) {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException
{
if (outputStream != null)
throw new IOException("output stream already called for this response");
else {
outputStream = getResponse().getOutputStream();
copier = new ServletOutputStreamCopier(this.outputStream);
return copier;
}
}
@Override
public PrintWriter getWriter() throws IOException
{
if (outputStream != null)
throw new IOException("print writer already called for this response");
else {
outputStream = getResponse().getOutputStream();
copier = new ServletOutputStreamCopier(outputStream);
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()));
return writer;
}
}
@Override
public void flushBuffer() throws IOException
{
if (writer != null)
writer.flush();
else if (copier != null)
copier.flush();
}
public String getContent()
{
String content = "";
try {
content = IOUtils.toString(copier.getCopyBuffer(), getResponse().getCharacterEncoding());
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
}
и мой класс ServletOutputStreamCopier (класс, который копирует содержимоепоток в ByteArrayOutputStream
):
public class ServletOutputStreamCopier extends ServletOutputStream {
private ServletOutputStream outputStream;
private ByteArrayOutputStream copier;
/**
*
*/
public ServletOutputStreamCopier(ServletOutputStream outputStream) {
super();
this.outputStream = outputStream;
this.copier = new ByteArrayOutputStream();
}
@Override
public boolean isReady()
{
return this.outputStream.isReady();
}
@Override
public void setWriteListener(WriteListener listener)
{
}
@Override
public void write(int b) throws IOException
{
if (this.copier == null)
this.copier = new ByteArrayOutputStream();
if (this.outputStream == null)
throw new IOException("outputStream is null");
this.copier.write(b);
this.outputStream.write(b);
}
public byte[] getCopyBuffer()
{
return this.copier.toByteArray();
}
}
и, наконец, вставить его в загрузочный фильтр пружины:
@Component
public class LoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain
) throws ServletException, IOException
{
HttpServletResponseCopier responseWrapper = new HttpServletResponseCopier(response);
filterChain.doFilter(request, responseWrapper);
System.out.println("response body: "+responseWrapper.getContent());
}
}
, который выводит это:
"body": <response body here>