【问题标题】:ContainerResponseFilter runs twice, header not modifiedContainerResponseFilter 运行两次,标头未修改
【发布时间】:2018-02-23 07:26:16
【问题描述】:

过滤器拦截所有请求并在响应中添加自定义标头。

当我实现 ContainerResponseFilter 时,过滤器方法运行了两次:

@Provider
public class MyCustomFilter implements ContainerResponseFilter throws IOException {

   @Override
   public void filter(ContainerRequestContext containerRequestContext, 
    ContainerResponseContext containerResponseContext) {
       containerResponseContext.getHeaders().add("My-Key", "myvalue");
    }

}

而且,提供给客户端的响应确实不包含标头。

我已尝试调试 Jetty 和 Jersey 配置,并将问题缩小到以下我无法修改的旧控制器逻辑:

        OutputStream out = response.getOutputStream();
        PrintWriter printout = new PrintWriter(out);
        JSONObject obj = new JSONObject(dummyData);
        printout.print(obj);

似乎直接写入响应流会触发一些导致额外处理阶段的 JAX-RS 生命周期链。

我在 Jersey 2.52.1 和 Jetty 9.4.4。

【问题讨论】:

  • 我在 Jetty 上使用 2 个连接器和虚拟主机运行。我试过只运行一个。一样。我正在为 Jersey 运行两个不同的 ResourceConfig,但只为其中一个注册过滤器包。

标签: java filter jersey jetty servlet-filters


【解决方案1】:

解决了。

似乎访问输出流并执行 printwriter.print() 触发了 HttpServletResponse "WRITE" 状态并开始向客户端返回响应。

所以在我的控制器中:

@GET
@Path("/seatemperatures")
public HttpServletResponse modifyResponse(@Context HttpServletRequest request, @Context HttpServletResponse response) {
    UtilClass.workOnResponse(request, response); //this uses printwriter.write()
    return response;
}

我不得不将返回类型更改为 void:

@GET
@Path("/seatemperatures")
public void modifyResponse(@Context HttpServletRequest request, @Context HttpServletResponse response) {
    UtilClass.workOnResponse(request, response);
}

从控制器返回响应对象似乎会导致内部 500 错误并有效地尝试返回两个响应对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多