在提交响应后,是否可以从servlet过滤器转发或重定向?

时间:2010-08-04 15:18:41

标签: java servlets servlet-filters forward

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

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>

2 个答案:

答案 0 :(得分:16)

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

答案 1 :(得分:5)

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

编辑:

有关使用CharResponseWrapper的代码示例,请参阅Programming Customized Requests and Responses部分。该示例使用自定义Writer,但可以轻松扩展为OutputStream。根据您的Servlet的使用方式,您需要覆盖getWriter()getOutputStream()中的一个或两个,以延迟将任何内容提交到原始响应。此外,您需要覆盖isCommitted()以返回false,以便可以在过滤器链的任何时间执行转发。您还需要覆盖resetBuffer()以初始化新的OutputStream / Writer,以便在重定向/转发后存储新内容(包括标题)。