Spring Boot Actuator 的
Trace
在捕获输入/输出 HTTP 参数、标头、用户等方面做得很好。我想扩展它以捕获 HTTP 响应的正文,这样我就可以拥有完整的视图网络层进出的内容。看看TraceProperties
,看起来没有办法配置响应正文捕获。是否有一种“安全”的方法来捕获响应正文而不弄乱它发送回的任何字符流?
最近,我写了一篇关于自定义 Spring Boot Actuator 的 trace
端点的
博客文章,在使用 Actuator 时,我有点惊讶
response body
不是支持跟踪的属性之一。
TeeFilter
想出了一个快速的解决方案。
为了复制响应的输出流,我复制并使用了 TeeHttpServletResponse 和 TeeServletOutputStream ,没有进行太多检查。
WebRequestTraceFilter
,例如:
@Component
public class RequestTraceFilter extends WebRequestTraceFilter {
RequestTraceFilter(TraceRepository repository, TraceProperties properties) {
super(repository, properties);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
TeeHttpServletResponse teeResponse = new TeeHttpServletResponse(response);
filterChain.doFilter(request, teeResponse);
teeResponse.finish();
request.setAttribute("responseBody", teeResponse.getOutputBuffer());
super.doFilterInternal(request, teeResponse, filterChain);
}
@Override
protected Map<String, Object> getTrace(HttpServletRequest request) {
Map<String, Object> trace = super.getTrace(request);
byte[] outputBuffer = (byte[]) request.getAttribute("responseBody");
if (outputBuffer != null) {
trace.put("responseBody", new String(outputBuffer));
}
return trace;
}
}
现在,您可以在 JSON
responseBody
端点服务中看到 trace
。
来自一位 Spring 维护者:
从来没有开箱即用地支持跟踪请求和响应正文。对跟踪参数的支持已被删除,因为当请求以 POST 形式发送数据时,需要读取整个请求正文。
@Component
public class RequestTraceFilter extends HttpTraceFilter {
public RequestTraceFilter(HttpTraceRepository repository, HttpExchangeTracer tracer) {
super(repository, tracer);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
TeeHttpServletResponse teeResponse = new TeeHttpServletResponse(response);
filterChain.doFilter(request, teeResponse);
teeResponse.finish();
log.info(new String(teeResponse.getOutputBuffer()));
super.doFilterInternal(request, teeResponse, filterChain);
}
}
我还从上面的答案中窃取了TeeHttpServletResponse的使用,将其和TeeServletOutputStream放在与过滤器相同的包中。