重定向是不是保证会延迟到所有 servlet 过滤器都已处理完毕?

Posted

技术标签:

【中文标题】重定向是不是保证会延迟到所有 servlet 过滤器都已处理完毕?【英文标题】:Is a redirect guaranteed to be delayed until all servlet filters have been processed?重定向是否保证会延迟到所有 servlet 过滤器都已处理完毕? 【发布时间】:2015-01-08 06:46:07 【问题描述】:

我有一个带有两个 servlet 的 Java Web 应用程序。一个 servlet 用于创建新用户帐户,另一个用于编辑现有用户帐户(给定其唯一 ID)。

如果调用 servlet 1 ("/create-user"),它会生成一个具有唯一 ID 的新用户帐户,然后重定向到 servlet 2:"/edit-user?uid=123"。 Servlet 2 然后加载给定用户帐户的数据。

现在特别的事情: 两个 servlet 执行的所有操作都在一种事务中执行。事务由 servlet 过滤器启动并最终提交(伪代码):

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
    Transaction t = Transaction.startTransaction();
    try 
        chain.doFilter(request, response);
     finally 
        t.commit();
    

在事务提交之前,servlet 1 生成的用户帐户对外界(因此 servlet 2)不可见。

这在基于 Tomcat、WebSphere 和 JBoss 的各种版本的 100 多个安装中完美运行。但是有一个基于 WebLogic 10.3.5.0 的安装,我们在 servlet 2 中遇到异常,因为它无法找到用户帐户。似乎重定向指令被发送回客户端,并且客户端在原始请求被 servlet 过滤器后处理之前将其发送到服务器。因此,新用户帐户尚未提交,servlet 2 无法加载其数据。

我知道重定向是作为“位置”HTTP 响应标头实现的。我也知道,在服务器端生成完整响应之前,Web 服务器可能会开始将数据发送回客户端(从响应标头开始)。但是,在原始 HTTP 请求完全处理之前,是否允许客户端遵循重定向?是否不能保证在重定向发生之前原始请求已被完全处理(包括所有 servlet 过滤器)?

【问题讨论】:

客户端如何知道请求没有被完全处理?它所知道的是它已经收到了一个完整的 HTTP 响应。服务器在发送完响应的所有字节后做什么与浏览器无关,甚至无法知道。对我来说,你的架构被打破了。事务应在向客户端发送响应之前提交。 我同意。除了改变架构之外的另一个选择可能是使用响应包装器来缓冲输出并在提交后将其传递给原始响应对象。 【参考方案1】:

您不应该使用 servlet 过滤器来处理用户事务。它必须围绕 servlet 完成。如果交易失败怎么办?您没有办法发送错误页面,因为 HTTP 响应可能已经提交。

在您的情况下,http 响应可能在您的过滤器提交之前已经发送到客户端。

我建议重构您的代码以在您的 servlet 中设置事务方面,这样您的问题肯定会消失。

【讨论】:

以上是关于重定向是不是保证会延迟到所有 servlet 过滤器都已处理完毕?的主要内容,如果未能解决你的问题,请参考以下文章

如何重定向到 Servlet 过滤器中的当前页面?

在 servlet 过滤器中使用请求参数将 JSF ajax 请求重定向到 URL

Servlet过滤器重定向:如何在chain.doFilter(request,resp)之后重定向;

如何在从 servlet 过滤器执行 HTTP 重定向时保留请求正文

如何在 java Servlet 过滤器中更改传入 URL 并将请求重定向到新 URL [重复]

我应该使用 servlet 还是过滤器来重定向 URL?