你总是在发布后重定向吗?如果是,您如何管理它?

2022-09-03 14:33:36

假设您正在提交一个表单,该表单会影响您的数据库(添加记录/删除记录/更新它们),这就是您的请求的样子:

POST /application/action=update

现在,假设您已完成更新,因此您希望将用户带到主页。

Response.sendRedirect /application/action=home

这非常有效。用户在POST后被发送重定向,因此即使用户尝试通过按F5刷新页面,您也很好。但是,如果您这样做,这将不起作用:

requestDispatcher.forward(/application/action=home)

鉴于有一种情况,您必须在完成更新后显示不同类型的错误/成功消息,因此您很可能在POST后进行转发。在这种情况下,如何避免更新操作发生两次?

我发现相当有趣的是,许多安全网站(银行)/支付网关倾向于通过在屏幕上放置文本来通知用户,例如“请不要按后退/刷新按钮”。

难道没有更好的方法来处理这个问题吗?除了要求用户不要按下这些按钮?当我上次检查时,有一种叫做“垂直响应缓存”的东西。一个筛选器,它将标识会话中请求的唯一性,并在请求重复时尝试发送缓存的响应。有没有更简单的方法来解决这个经典问题?

以下是我正在谈论的垂直响应缓存解决方案的链接:http://www.fingo.info/en/articles/_1.html。但是,我不确定这到底有多好。


答案 1

是的,我认为您应该在POST之后重定向,但API请求除外。如果不这样做,您不仅需要担心在用户使用后退按钮时获得重复的POST,而且浏览器还会在用户尝试使用后退按钮时为用户提供烦人的对话框。

Response.sendRedirect在实践中是有效的,但从技术上讲,这是为此目的发送了错误的HTTP响应代码。sendRedirect 发送 302,但用于将 POST 转换为 GET 的正确代码是 303。(但是,大多数浏览器会像303一样对待302,如果他们在响应POST时获得它)

通常,您希望重定向将用户发送到将显示其更改效果的任何视图。例如,如果他们编辑一个小部件,则应将其重定向到该小部件的视图。如果他们删除了一个小部件,则应将他们重定向到该小部件存在时会出现的视图(可能是小部件列表)。

有时,最好有一条状态消息,以进一步说明发生了操作的事实。执行此操作的一种简单方法是为视图设置一个通用参数,该参数在设置后将显示操作已完成消息。例如:

/widget?id=12345&msg=Widget+modified.

此处的“msg”参数包含消息“已修改小部件”。这种方法的一个缺点是,恶意网站可能会向用户提供令人困惑/误导性的消息。例如:

/account?msg=Foo+Corp.+hates+you.

如果您真的担心这一点,则可以将邮件的过期签名作为附加参数。如果签名无效或已过期,则根本不显示消息。


答案 2

解决在 POST 到 GET 重定向后向用户显示状态消息问题的最佳解决方案是使用用户会话。

如何

将属性添加到用户会话,其值作为要显示的消息集。例如。

userSession.put("success_messages", new HashSet<String>(){"Success", "Check your account balance"});
userSession.put("warning_messages", new HashSet<String>(){"Your account balance is low. Recharge immediately"});

并有一个过滤器,用于扫描用户会话中的这些特定属性并输出消息。筛选器应在读取一次后删除属性,因为状态消息通常只显示一次。


推荐