You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring集成Jersey时,如何在HTTP响应处理完成后清除MDC?

解决方案:利用Jersey的CompletionCallback清理MDC

Jersey提供了CompletionCallback接口,专门用于在响应完全处理完成(包括Multipart响应的转换、写入客户端等所有操作)后执行回调逻辑,正好满足你延迟清理MDC的需求。

1. 接口级别的局部处理

直接在返回的Response对象上注册CompletionCallback,仅针对当前接口生效:

@Path("/status/{requestID}")
@GET
public Response getStatus(@PathParam("requestID") String requestId) {
    MDC.put("myRequestID", requestId);
    // 构建Multipart响应的逻辑
    MultiPart multiPart = new MultiPart();
    // 添加响应内容,比如文件、文本等
    multiPart.bodyPart(new BodyPart("status content", MediaType.TEXT_PLAIN_TYPE));
    
    Response response = Response.ok(multiPart).build();
    
    // 注册响应完成回调,清理MDC
    response.register(new CompletionCallback() {
        @Override
        public void onComplete(Throwable throwable) {
            MDC.clear();
        }
    });
    
    return response;
}

2. 全局统一处理(推荐)

如果需要所有接口自动处理MDC清理,可以通过全局过滤器结合CompletionCallback实现,避免重复代码:

步骤1:实现ContainerRequestFilter,请求进入时设置MDC

@Provider
public class MdcRequestFilter implements ContainerRequestFilter {
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        String requestId = requestContext.getUriInfo().getPathParameters().getFirst("requestID");
        if (requestId != null) {
            MDC.put("myRequestID", requestId);
        }
        // 注册全局的响应完成回调
        requestContext.setProperty("mdcCleanup", new CompletionCallback() {
            @Override
            public void onComplete(Throwable throwable) {
                MDC.clear();
            }
        });
    }
}

步骤2:实现ContainerResponseFilter,将全局回调绑定到每个响应

@Provider
public class MdcResponseFilter implements ContainerResponseFilter {
    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        CompletionCallback cleanupCallback = (CompletionCallback) requestContext.getProperty("mdcCleanup");
        if (cleanupCallback != null && responseContext.getResponse() instanceof Response) {
            ((Response) responseContext.getResponse()).register(cleanupCallback);
        }
    }
}

步骤3:注册过滤器到Jersey

确保过滤器被Jersey扫描到,或在Spring配置中手动注册:

@Configuration
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        register(MdcRequestFilter.class);
        register(MdcResponseFilter.class);
        // 扫描接口所在包
        packages("your.package.name");
    }
}

注意事项

  • CompletionCallback的onComplete方法无论响应处理成功还是失败都会被调用,不会因异常导致MDC未清理。
  • 若接口使用异步响应(AsyncResponse),同样可以通过asyncResponse.register(new CompletionCallback())的方式注册回调,逻辑一致。

内容的提问来源于stack exchange,提问作者user007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:54:22