Java Servlet过滤器 - 根据状态修改响应头

时间:2017-02-07 21:25:19

标签: java servlet-filters

我正在尝试编写一个servlet过滤器,它会根据请求的状态为响应添加标头。我知道我必须在传递给chain.doFilter之前用HttpServletResponseWrapper包装响应,但是标题永远不会被发送,所以我显然遗漏了一些非常明显的东西。

代码类似于:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
   HttpServletResponse httpServletResponse = (HttpServletResponse) response;
   HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(httpServletResponse);

   chain.doFilter(request, responseWrapper);

   if(responseWrapper.getStatus() < 400)
   {
      responseWrapper.addHeader("X-Custom-Foobar", "abc");
   }
}

在检查完成之前,我是否必须在包装器中捕获以防止响应发送到客户端?

4 个答案:

答案 0 :(得分:1)

您需要扩展 HttpResponseWrapper()并覆盖相应的方法。只使用香草HttpResponseWrapper本身就完全没有。

答案 1 :(得分:0)

所以关于这个规范的令人沮丧的部分是你必须完全拦截ServletOutputStream并缓冲它。我最后在这里举例:: https://stackoverflow.com/a/11027170/76343

基类HttpServletResponseWrapper是完整的直通,只要输出流关闭,对响应的所有进一步修改都会静音。

不幸的是,似乎没有更优雅的方法来实现这一目标。

答案 2 :(得分:0)

这实际上是可能的。但是因为调用 chain.doFilter(request, response) 后响应已经提交,所以我们必须在收到状态码之后,但在提交响应之前设置标头。下面是一个例子:

public class HeadersFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException,
                                                                                             ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        chain.doFilter(request, new ResponseWrapper(response));
    }

    public static class ResponseWrapper extends HttpServletResponseWrapper {
        public ResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public void setStatus(int sc) {
            super.setStatus(sc);

            // SET YOUR HEADERS HERE
            // setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        }
    }

    @Override
    public void destroy() {
    }
}

答案 3 :(得分:0)

这段代码的顺序颠倒了:

   chain.doFilter(request, responseWrapper);

   if(responseWrapper.getStatus() < 400)
   {
      responseWrapper.addHeader("X-Custom-Foobar", "abc");
   }

试试这个:

   if(responseWrapper.getStatus() < 400)
   {
      responseWrapper.addHeader("X-Custom-Foobar", "abc");
   }

   chain.doFilter(request, responseWrapper);

doFilter 方法不会返回到您的方法,直到在线路上发送响应之后。