Spring MVC-HttpSession.setAttribute和model.addObject之间的区别


问题内容

我正在尝试最近学习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方法中。我从会话中获取 计数重新分配 它并在会话中 覆盖 它。但是我 看不到
jsp 的更新值 。但是,可以看到更新的shoppingCart对象已更新,尽管我没有覆盖会话对象(因为该对象是已在会话中的同一对象)。

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


问题答案:

首先,@SessionAttribute不必使用http会话。它使用SessionAttributeStore可以将任何内容作为后备存储的。仅默认实现使用http会话。

您的代码无法按预期工作的原因在于@SessionAttribute工作方式。

在调用控制器方法之前@SessionAttributes,您需要{"warenkorb", "count"}从会话中读取中列出的所有内容,并将其添加到模型中。

方法返回后,将使用该方法中 已添加到模型中的所有内容更新会话。

.addObject("count", count)

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

session.setAttribute("count", count)

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

当您使用@SessionAttributes@ModelAttribute(或通常使用Spring
MVC)时,请避免使用HttpSessionHttpRequest。甚至HttpResponse用途有限。拥抱Spring MVC而不是美丽:)