Spring生命周期问题:注释@SessionAttributes使会话属性的寿命比会话本身更长



以下是可以重现此问题的代码:

@Controller
public class FirstController {
    @RequestMapping(value = "firstpage", method = GET)
    public String myHander(HttpSession httpSession) {
        if (httpSession.getAttribute("someClass") == null) {
            httpSession.setAttribute("someClass", new SomeClass());
        }
        return "firstpage";
    }
}

如果会话中还没有内容,则第一个控制器将其放入会话中。

@Controller
@SessionAttributes(types = SomeClass.class)
public class SecondController {
    @RequestMapping(value = "secondpage", method = GET)
    public String myHandler(SomeClass someClass, HttpSession httpSession) {
        //asking spring for the SomeClass parameter, that's why we put it in the annotation.
        System.out.print(someClass.hashCode());
        httpSession.invalidate();
        return "secondpage";
    }
}

第二控制器终止会话。

在这两个jsp文件中,我都有以下代码,用于打印会话对象的哈希代码和会话属性的哈希代码:

session hash:
<%= session.hashCode() %>
<br/>
someclass hash:
<%= session.getAttribute("someClass").hashCode() %>

现在,如果我运行应用程序并访问"首页",我会得到这个:

会话哈希:1838367636

someclass哈希:1075505853

然后我访问"第二页",会得到这个:

会话哈希:842656294

someclass哈希:1075505853

我们可以看到会话本身发生了变化,因为第二个控制器会终止会话。但是会话属性(SomeClass类型)保持不变。

然后,如果我尝试重新访问"secondpage",会话对象每次都会更改,但会话属性保持不变。

为什么会话属性(应该附加到会话)的生命周期比会话本身更长?

附言:完整的代码在这里:https://github.com/cuipengfei/One-hundred-thousand-why/tree/master/20130701SessionAttributesLifeCycle/SpringMVC

您可以使用mvnjetty:run来运行它以重现问题。

此注释的文档不是特别清楚,但我的理解是,它用于在同一控制器中的方法之间共享值。当我读到以下内容时:

这通常会列出模型属性的名称或模型属性的类型,这些名称或类型应该透明地存储在会话或某些会话存储中,用作后续请求之间的表单备份bean

我将其解释为,每个控制器方法调用都将封装一个调用,以(1)在进入之前加载会话属性,(2)在退出时存储它们。这会有你所看到的行为。

注释的javadoc中的以下内容加强了这一点(imo):

对于永久会话属性,例如用户身份验证对象,请使用传统的session.setAttribute方法,而不是

如果他们告诉你使用标准函数来修改会话,这向我表明注释不仅仅是访问会话中项目的一种方式。

最后一个数据点是:如果这个注释是管理会话数据的方式,为什么要有会话范围的bean?

最新更新