代码之家  ›  专栏  ›  技术社区  ›  Daniel Alexiuc arunjitsingh

如果我忘记将Spring会话状态标记为“完成”,会发生什么?

  •  17
  • Daniel Alexiuc arunjitsingh  · 技术社区  · 16 年前

    在SpringMVC中,假设我使用@sessionattribute标记来定义sessionattribute,如下所示:

    @SessionAttributes(value = "myModel")
    public class MyController{
       ...
    }
    

    假设我忘记像这样对sessionstatus调用status.setComplete():

    @RequestMapping(method = RequestMethod.POST)
    public void doSomething(@ModelAttribute("myModel") MyModel model, SessionStatus status){
       ...
       //status.setComplete(); <-- Never gets called
    }
    

    模型会永远留在会议上吗?当用户浏览站点时,会话会越来越大吗?

    3 回复  |  直到 7 年前
        1
  •  12
  •   kaqqao    7 年前

    编辑2:请注意,此答案不再正确。见 @doanduyhai's answer 下面。

    编辑:请注意,这是针对Spring2.5和May的,但不一定确保Spring3.x也是如此。请仔细检查文档!

    这与甘道夫所说的一致。

    表单控制器为表单请求寿命建模,从表单的初始查看到表单提交。表单提交之后,表单控制器的工作就完成了,它将从会话中删除命令对象。

    因此,要将命令对象保留在表单工作流之间的会话中,需要手动管理会话。在一个干净的日志后,对象将从会话中删除。

    简而言之,我认为setComplete()方法只是一个很好的实践,但并不一定是必需的。

    编辑 我只是在我的春鉴里确认了这一点。我将引用它:

    如果不使用@sessionattribute,则 将在上创建新的命令对象 每个请求,即使在呈现 由于绑定错误而重新形成。如果 启用了此注释,则 命令对象将存储在 供后续使用的会话, 直到 表单成功完成。然后 将清除此命令对象 从会议开始。 这通常是 当命令对象是 需要的持久对象 不同请求相同 用于跟踪更改。

    基本上这就是我上面说的。它将它存储在会话中,直到a)调用setComplete()或b)控制器成功完成一个POST。

        2
  •  22
  •   riddle_me_this He Drunh    7 年前

    关于控制器退出后会话属性是否被清除,存在很大的争论。

    为了一劳永逸地澄清,我们可以看看 弹簧MVC 3.1.0释放 源代码。

    界面 org.springframework.web.bind.support.sessionAttributeStore网站 显示以下方法:

    void storeAttribute(WebRequest request, String attributeName, Object attributeValue);
    
    Object retrieveAttribute(WebRequest request, String attributeName);
    
    void cleanupAttribute(WebRequest request, String attributeName);
    

    默认实现是 org.springframework.web.bind.support.defaultsessionAttributeStore

    做一个“ 打开调用层次结构 “关于 清除属性() 在Eclipse中,我们可以看到该方法由两个不同的流调用:

    1) org.springframework.web.method.annotation.modelfactory模型工厂

    public void updateModel(NativeWebRequest request, ModelAndViewContainer mavContainer) throws Exception {
    
            if (mavContainer.getSessionStatus().isComplete()){
                this.sessionAttributesHandler.cleanupAttributes(request);
            }
            else {
                this.sessionAttributesHandler.storeAttributes(request, mavContainer.getModel());
            }
    
            if (!mavContainer.isRequestHandled()) {
                updateBindingResult(request, mavContainer.getModel());
            } 
        }
    

    2) org.springframework.web.bind.annotation.support.handlerMethodInvoker

    public final void updateModelAttributes(Object handler, Map<String, Object> mavModel,
                ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {
    
            if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
                for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
                    this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
                }
            }
    ...
    }
    

    很明显,在这两种情况下,只有在 this.sessionstatus.iscomplete()。 被称为。

    我深入研究了 默认会话属性存储 . 在引擎盖下,它得到了真实的 HTTP会话 对象来存储属性,以便同一会话中的其他控制器可以访问这些属性。

    所以不,会话属性不会在干净的日志后被删除。

        3
  •  1
  •   Gandalf    16 年前

    你有什么理由要这么做吗?

    从这个线程: @SessionAttribute Problem

    @sessionAttributes的工作方式与simpleFormController的sessionForm相同。它将命令(或@sessionattributes的任何对象)放在会话中,持续时间介于第一个请求和最后一个请求之间(大多数时间是初始GET和最后一个POST)。之后,这些东西就被移走了。