在提交响应后,是否可以从servletfilter转发或重定向?

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

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); } } 

我的部署描述符示例:

  MyFilter com.filters.MyFilter   MyFilter *.jsp REQUEST FORWARD  

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

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

编辑:

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