在过滤器中添加标头作为响应?

emi*_*lly 14 java spring-mvc httpresponse filter servlet-filters

我需要在每个响应中添加标头.我打算在下面做

public class MyFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        filterChain.doFilter(request, response);
            response.addHeader("Access-Control-Allow-Origin", "*"); 
    }

}
Run Code Online (Sandbox Code Playgroud)

我想这样做之后filterChain.doFilter(request, response),一旦控制器处理它,我只是在返回客户端之前添加标题.这是对的吗 ?

但按照如何编写响应过滤器?

chain.doFilter返回之后,对响应采取任何措施都为时已晚.此时,整个响应已发送到客户端,您的代码无法访问它.

以上陈述对我来说不合适.我不能添加标题后filterChain.doFilter(request, response)?如果不是为什么?

我正在使用spring mvc.

Lua*_*tti 17

filterChain.doFilter被叫之后,对响应采取任何措施都为时已晚.此时,整个响应已发送给客户端.

您需要在自己的类中构建一个包装响应,将这些包装器传递给doFilter方法并处理包装器中的任何处理.

已有响应包装器:HttpServletResponseWrapper您可以扩展.例如:

public class MyResponseRequestWrapper extends HttpServletResponseWrapper{
    public MyResponseRequestWrapper(HttpServletResponse response) {
        super(response);
    }
}
Run Code Online (Sandbox Code Playgroud)

你的过滤器:

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    HttpServletResponse myResponse = (HttpServletResponse) response;
    MyResponseRequestWrapper responseWrapper = new MyResponseRequestWrapper(myResponse);
    responseWrapper.addHeader("Access-Control-Allow-Origin", "*");
    filterChain.doFilter(request, myResponse);
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么要进行不必要的演员阵容?为什么使用不必要的变量 myResponse?为什么是包装纸?这一切都可以通过一个简单的方法实现:response.addHeader("headerName", "headerValue"); filterChain.doFilter(请求,响应); (4认同)
  • 为什么在您的示例中使用包装器而不是仅将标头添加到容器传递的原始实现中?我认为只有在你内部实现一些逻辑以确保你的标题不会被删除/覆盖在过滤器链的某个地方时,包装才有意义. (3认同)
  • @Luan - 在你上面的回答中,你不应该将 `responseWrapper` 传递给 `filterChain.doFilter` 吗? (2认同)
  • 谢谢栾的回答!!在我的情况下,我希望标题仅为 404 类型的响应设置,因此如答案中所述,我在包装类中添加了以下代码:`@Override public void sendError(int sc) throws IOException { if (sc = = 404) { this.setHeader("X-ServiceFabric", "ResourceNotFound"); } super.sendError(sc); }` (2认同)

Dav*_*žic 5

我在我的项目中使用 Spring 3.0.x:

public class MyFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException
    {
        response.addHeader("headerName", "headerValue");
        filterChain.doFilter(request, response);
    }
}
Run Code Online (Sandbox Code Playgroud)

工作正常。