7

逻辑是过滤器被命中,条件不成立,所以它通过过滤器链。提交响应后,过滤器被命中,现在条件为真(设置了请求属性)。它进入执行转发,但页面从不转发。我知道这与提交的响应有关,因为我测试了它在第一次到达链之前转发的不同逻辑,并且它确实转发成功。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest)request;

    if (some condition equals true) {
        httpServletRequest.getRequestDispatcher("/home.jsp").forward(request, response);
        return;
    } else {
        chain.doFilter(request, response);
    }
}

我的部署描述符中的示例:

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.filters.MyFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
    <dispatcher>REQUEST</dispatcher>  
    <dispatcher>FORWARD</dispatcher> 
</filter-mapping>
4

2 回答 2

16

an 的“已提交”状态HttpServletResponse实际上是一种表示响应标头是否已写入底层套接字的方式。一个“承诺的”响应已经(至少)写了第一行。由于响应的第一行包含状态代码,因此您无法更改已提交响应的状态代码......这意味着将状态更改为 3xx 进行重定向为时已晚。同样,您不能进行本地转发,因为您已经开始发送响应。

于 2010-08-04T15:48:54.407 回答
5

您可以通过使用自定义HttpServletResponse来实现您想要的。您将这个包装的 HttpServletResponse 传递到过滤器链中。您可以提供存储所有写入请求的本地 OutputStream、存储状态代码和标头的本地变量。回到过滤器后,您可以决定执行重定向或将本地变量的结果从包装器复制回原始 ServletResponse(即设置状态代码和标头并将结果从本地输出流复制到servlet 响应的输出流)。

编辑:

有关使用. _ CharResponseWrapper该示例使用自定义 Writer,但可以轻松将其扩展为 OutputStream。根据您的 Servlet 的使用方式,您需要覆盖其中一项或两项,getWriter()getOutputStream()延迟将任何内容提交到原始响应中。此外,您将需要覆盖isCommitted()return false,以便可以随时在过滤器链中执行转发。您还需要重写resetBuffer()以在重定向/转发之后初始化新的OutputStream/Writer以存储新内容(包括标题)。

于 2011-12-14T02:48:12.813 回答