【问题标题】:Spring MVC - difference between HttpSession.setAttribute and model.addObjectSpring MVC - HttpSession.setAttribute 和 model.addObject 之间的区别
【发布时间】:2013-04-29 07:19:07
【问题描述】:

我最近正在尝试学习 Spring MVC。 @ModelAttribute 注解和 HttpSession 的功能我好像不太了解。

@SessionAttributes({"shoppingCart", "count"})
public class ItemController {

@ModelAttribute("shoppingCart")
public List<Item> createShoppingCart() {
    return new ArrayList<Item>();
}

@ModelAttribute("count")
public Integer createCount() {
    return 0;
}

@RequestMapping(value="/addToCart/{itemId}", method=RequestMethod.GET)
public ModelAndView addToCart(@PathVariable("itemId") Item item, 
        @ModelAttribute("shoppingCart") List<Item> shoppingCart, @ModelAttribute("count") Integer count) {

    if(item != null) {
        shoppingCart.add(item);
        count = count + 1;
    }

    return new ModelAndView(new RedirectView("showAllItems")).addObject("count", count);
}

@RequestMapping(value="/deleteFromCart/{itemId}", method=RequestMethod.GET)
public ModelAndView deleteFromCart(@PathVariable("itemId") Item item, 
        HttpSession session) {

    List<Item> list = (List<Item>) session.getAttribute("shoppingCart");
    list.remove(item);
    //session.setAttribute("shoppingCart", list);

    Integer count = (Integer) session.getAttribute("count");
    count = count - 1;
    session.setAttribute("count", count);

    return new ModelAndView(new RedirectView("showAllItems"));
}

ShoppingCart 和 count 是会话属性。

问题出在 deleteFromCart 方法中。我从会话中获取 count重新分配它并在会话中覆盖它。但我 看不到 jsp 上 count 的更新值。但是,可以看到更新后的 shoppingCart 对象已更新,尽管我没有覆盖会话对象(因为该对象与已经在会话中的对象相同)。

但是为什么计数没有更新,虽然我用 session.setAttribute 覆盖了它? 当我将新的计数对象添加到模型(model.addObject(“count”,count))时,我可以看到更新的计数值。但是为什么 session.setAttribute 没有给出相同的结果呢?

【问题讨论】:

    标签: spring spring-mvc session-variables httpsession modelattribute


    【解决方案1】:

    model.addObject 将对象放入请求范围,而HTTPsession.setAttribute 将其放入会话范围。并且由于 jsp 上的变量是按下一个顺序解析的:页面范围 -> 请求范围 -> 会话范围 -> 应用范围,所以你得到了你得到的。

    【讨论】:

    • 但是我已经使用@SessionAttributes({"warenkorb", "count"}) 将这两个属性定义为上面的会话属性。当我用 session.setAttribute("count", count) 覆盖属性计数时,它不应该用会话范围更改属性吗?也许我不应该把问题写成“setAttribute 和 addObject 之间的区别”,而是 deleteFromBasket 方法中使用的 2 个会话对象之间的区别,这两者都导致不同的方式(warenkorb 已更新,count 仍然是旧的 count 对象) .
    • Fuh,终于解决了.. 将您的方法签名更改为public ModelAndView deleteFromBasket(@PathVariable Integer position, @ModelAttribute("warenkorb") List&lt;Item&gt; warenkorb, @ModelAttribute("count") Integer count, ModelMap modelMap) 并在会话中设置属性:modelMap.addAttribute("count", --count);
    • 当我在你写的时候改变方法签名时,我知道它可以工作:) 我的 addToBasket 方法的工作方式相同。我只是想理解一般概念,尝试使用不同的东西,比如 HttpSession等等。不过,非常感谢。
    【解决方案2】:

    首先,@SessionAttribute 不必使用 http 会话。它使用SessionAttributeStore,它可以有任何东西作为其后备存储。只有默认实现使用 http 会话。

    您的代码无法按预期运行的原因在于@SessionAttribute 的工作原理。

    在调用控制器方法之前,从会话中读取@SessionAttributes(在您的情况下为{"warenkorb", "count"})中列出的所有内容并添加到模型中。

    方法返回后会话会更新为方法中添加到模型的所有内容。

    .addObject("count", count)
    

    -> 计数被添加到模型中,然后添加到会话中。

    session.setAttribute("count", count)
    

    -> 计数被添加到会话而不是模型。它将在下一次调用任何控制器方法之前添加到模型中。但就目前而言,该模型仍然具有旧的count。模型是添加到请求中的内容。如果可以在请求范围内找到属性,则 jsp 不关心会话中的内容。

    当你使用@SessionAttributes@ModelAttribute(或一般的Spring MVC)时,请避免使用HttpSessionHttpRequest。甚至HttpResponse 的用途也有限。拥抱Spring MVC的美丽吧:)

    【讨论】:

    • 所以基本上;在调用控制器方法之前,会话会更新模型。在该方法之后,模型更新会话。因此,唯一一个同时包含在 Session 和 Model 中的相同属性可以具有不同值的情况是,在控制器方法中。非常感谢。
    【解决方案3】:

    Java 方法参数是按值传递的。您可以在方法内为这个参数分配任何您想要的东西,但在它之外不会有任何效果。 Insisde 您正在处理参数副本的方法

    【讨论】:

      猜你喜欢
      • 2015-12-31
      • 2018-03-24
      • 1970-01-01
      • 2015-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多