为什么在GET重定向时会清除SessionAttributes?

IT小君   2023-09-16T19:57:55
为了简化起见,这些代码片段将被缩短。这样做的目的是获取一个GET参数,将其设置在会话中,并重定向回GET,同时移除URL参数。基本上是URI清理。如果有更好/更简单的方法来实现这个功能,我很乐意听到。 我有一个如下所示的控制器: ```java @Controller @RequestMapping("/path/page.xhtml") @Scope(BeanDefinition.SCOPE_PROTOTYPE) @SessionAttributes({ "myParam1", "myParam2" }) public class MyController { @RequestMapping(method = RequestMethod.GET, params = { "urlParam2" }) public String handleUriParam(@RequestParam(value = "urlParam2", required = false) final Long urlParam2, final RedirectAttributes redirs) { // 在这一点上,myParam1已经设置在会话中。 // 现在将参数设置为闪存属性,并使用会话变量的名称 redirs.addFlashAttribute("myParam2", urlParam2); return "redirect:/path/page.xhtml"; } @RequestMapping(method = RequestMethod.GET, params = {}) public String doGetStuff(ModelMap model) { // 使用myParam1和myParam2做一些事情。 // 问题是,myParam2在会话中,但myParam1不在! } } ``` 就像代码所说的,当重定向发生时,某种方式上的myParam1被取消设置。我可以通过将ModelMap传递给handleUriParam方法并手动将myParam1添加到闪存属性中来解决这个问题,但在我看来,这似乎违背了目的。 为什么重定向后,SessionAttribute myParam1会被移除? 有没有更好的方法从URI中提取参数并将它们放在会话中? 更新 所以似乎无论何时使用RedirectAttributes,您必须确保将您希望带入重定向的任何SessionAttribute放在FlashAttributes中,否则它们将丢失。我想这是因为SessionAttribute是从ModelMap中取出的(在使用时被FlashAttributes替换)。这是Spring的一个bug还是有意为之的行为?如果是有意为之的,有人能解释一下为什么吗?我以为SessionAttribute应该一直保持到会话完成才被移除。 类似的StackOverflow帖子在这里。 附录 鉴于提供的答案,我仍然困惑于如何在将它们放在用户会话中的同时清除URI参数。我考虑的一个选项是为我正在尝试存储的半原始对象(java.lang.Integer、java.lang.String)创建一个包装器,因为它们不会被放置在URI字符串中,但是这对我来说似乎有点繁琐。如果有人有更好的方法来接受GET参数,将它们存储在用户会话中,并从用户的地址栏中清除它们(这将需要重定向),我将很乐意使用它。
评论(1)
IT小君

所以我在代码和互联网上寻找原因,为什么它不起作用。

Spring有两个完全独立的模型映射 - 一个用于标准视图渲染,另一个用于重定向时。这可以在ModelAndViewContainer中观察到。

现在,会话属性的持久化是基于mavContainer#getModel()的结果进行的。对于重定向场景,它返回重定向模型。因此,在标准Model / ModelMap上设置的内容会丢失。

这在谈论标准模型属性时是有道理的。模型主要用于将对象传递给视图。在使用重定向时,您处理的是完全不同的情况。您希望通过HTTP重定向传递对象 - 因此有了分离的基于字符串和闪存的模型。

然而,我觉得在设计这个功能时,他们忘记了会话属性。在Spring的Jira中有一些很好的讨论,但没有一个解决了这个具体问题。

所以是的...这可能是一个Spring的Jira讨论的话题。并且这可能被归类为一个bug,因为这会阻止任何人在使用重定向时设置会话模型属性。强制Spring通过RedirectAttributes#addFlashAttribute存储会话属性在我看来是一种hack,而且有点自身的bug

2023-09-16T19:58:16   回复