我想在 Post HandlerInterceptor 期间获取响应主体,但它是空的。
spring-boot.版本:2.7.4
CustomPostHandlerInterceptor.java
@Component
@Order(1)
public class CustomPostHandlerInterceptor implements HandlerInterceptor {
@Override
public final boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
@Override
public final void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
ContentCachingResponseWrapper resp = new ContentCachingResponseWrapper(response);
byte[] responseBody = resp.getContentAsByteArray();
String res = new String(responseBody, StandardCharsets.UTF_8);
}
@Override
public final void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
}
}
控制器类
@RestController
@RequestMapping("/exampleRest")
public class ExampleRest {
@RequestMapping("/getUsername")
@GetMapping
public String getUsername() {
return "michael";
}
}
我想从 HttpServletResponse 获取响应正文。 我尝试了不同的方法,但结果都是空的。 我该如何解决?
您必须首先缓存响应,您可以从spring扩展OncePerRequestFilter,然后缓存您的响应,以下代码注册一个过滤器,为您的请求和响应创建一个ContentCachingWrapper,使用它您应该能够得到使用您提到的代码进行响应。
@Component
public class CachingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new ContentCachingRequestWrapper(request), new ContentCachingResponseWrapper(response));
}
据我所知,该回复只能读取一次,因此您需要复制它。
您需要一个过滤器,如下所示:
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
@Component
public class LogFilter extends HttpFilter {
private FilterConfig filterConfigObj;
public void init(FilterConfig config) throws ServletException {
this.filterConfigObj = config;
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException {
HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((HttpServletResponse) response);
try {
chain.doFilter(request, responseCopier);
responseCopier.flushBuffer();
} finally {
byte[] copy = responseCopier.getCopy();
System.out.println(new String(copy, response.getCharacterEncoding()));
}
}
}
以及这些依赖类来读取和保存响应。
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class HttpServletResponseCopier extends HttpServletResponseWrapper {
private ServletOutputStream outputStream;
private PrintWriter writer;
private ServletOutputStreamCopier copier;
public HttpServletResponseCopier(HttpServletResponse response) throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}
if (outputStream == null) {
outputStream = getResponse().getOutputStream();
copier = new ServletOutputStreamCopier(outputStream);
}
return copier;
}
@Override
public PrintWriter getWriter() throws IOException {
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
if (writer == null) {
copier = new ServletOutputStreamCopier(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
copier.flush();
}
}
public byte[] getCopy() {
if (copier != null) {
return copier.getCopy();
} else {
return new byte[0];
}
}
}
和
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
public class ServletOutputStreamCopier extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream copy;
public ServletOutputStreamCopier(OutputStream outputStream) {
this.outputStream = outputStream;
this.copy = new ByteArrayOutputStream(1024);
}
@Override
public void write(int b) throws IOException {
outputStream.write(b);
copy.write(b);
}
public byte[] getCopy() {
return copy.toByteArray();
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return true;
}
@Override
public void setWriteListener(WriteListener listener) {
// TODO Auto-generated method stub
}
}