- 帖子详情
为什么在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参数,将它们存储在用户会话中,并从用户的地址栏中清除它们(这将需要重定向),我将很乐意使用它。
所以我在代码和互联网上寻找原因,为什么它不起作用。
Spring有两个完全独立的模型映射 - 一个用于标准视图渲染,另一个用于重定向时。这可以在
ModelAndViewContainer
中观察到。现在,会话属性的持久化是基于
mavContainer#getModel()
的结果进行的。对于重定向场景,它返回重定向模型。因此,在标准Model
/ModelMap
上设置的内容会丢失。这在谈论标准模型属性时是有道理的。模型主要用于将对象传递给视图。在使用重定向时,您处理的是完全不同的情况。您希望通过HTTP重定向传递对象 - 因此有了分离的基于字符串和闪存的模型。
然而,我觉得在设计这个功能时,他们忘记了会话属性。在Spring的Jira中有一些很好的讨论,但没有一个解决了这个具体问题。
所以是的...这可能是一个Spring的Jira讨论的话题。并且这可能被归类为一个bug,因为这会阻止任何人在使用重定向时设置会话模型属性。强制Spring通过
RedirectAttributes#addFlashAttribute
存储会话属性在我看来是一种hack,而且有点自身的bug。