日志记录(MDC)当响应失败时,我需要设置一个自定义标头,如下所示:
public class MDCFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
MDC.put("trackingId", UUID.randomUUID().toString());
try {
chain.doFilter(request, response);
} catch (Throwable throwable) {
//suppress
}
if (((HttpServletResponse) response).getStatus() >= 300) {
((HttpServletResponse) response).setHeader("x-tracking-id", MDC.get("trackingId"));
// ((HttpServletResponse) response).getHeader("x-tracking-id"); //this returns null
}
MDC.remove("trackingId");
}
}
但这不起作用,没有设置标题。如果我在chain.doFilter
之前设置报头,它可以工作,但我需要尽可能晚地设置此过滤器,我需要知道响应状态是OK
还是失败。
您需要在设置状态后立即设置报头,而不是在响应已经发送到客户端之后。这是一条不归路。可以使用HttpServletResponseWrapper
来修饰setStatus()
方法的行为。
例如,
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
MDC.put("trackingId", UUID.randomUUID().toString());
chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
@Override
public void setStatus(int status) {
super.setStatus(status);
if (status >= 300) {
setHeader("x-tracking-id", MDC.get("trackingId"));
}
}
});
}
finally {
MDC.remove("trackingId");
}
}
注意,我还修正了草率的异常处理。