如何在Spring MVC中维护会话?

时间:2012-09-17 10:32:05

标签: java spring session spring-mvc

使用spring MVC,我需要将我的对象存储到会话中,我应该使用jstl在几个jsp页面中使用相同的对象。我试过这样的:

ModelAndView modelAndView = new ModelAndView("admin/addproduct", "category", categorynameList);

但我无法访问除addproduct页面之外的其他jsp页面的类别。

我该怎么做?

4 个答案:

答案 0 :(得分:1)

您可以将会话直接传递给任何带注释的控制器方法:

@RequestMapping("somePathName")
public String someHandler(HttpSession session) {
  session.setAttribute(...

答案 1 :(得分:1)

Spring MVC提供了多种机制来隐藏HttpSession的明显用法。

查看@SessionAttributes注释,它允许您定义控制器将存储在会话中的属性;此机制主要用于维护处理程序的会话状态,并且通常在对话完成后清除该状态。

此外,您可以将bean定义为在应用程序上下文中作用域的会话,然后使用ScopedProxyFactoryBean(通过在bean定义中简单地添加<aop:scoped-proxy/>元素),从而能够在您的bean中注入该bean单身控制器。

答案 2 :(得分:0)

注释 @SessionAttributes用于班级。通常它在@Controller类上使用。它的价值&#39; element的类型为String [],其值是@ModelAttribute在方法级别或处理程序的方法参数级别上使用的匹配名称。

让我们考虑以下安排:

@Controller
@SessionAttributes("visitor")
@RequestMapping("/trades")
public class TradeController {

    @ModelAttribute("visitor")
    public Visitor getVisitor (....) {
        return new Visitor(....);
    }
  ....
}

在上面的代码中,当一个请求进来时,Spring会做的第一件事是注意@SessionAttributes(&#39; visitor&#39;)然后尝试找到&#39; visitor&#39;的值。在javax.servlet.http.HttpSession中。如果它没有找到该值,那么具有@ModelAttribute的方法具有相同的名称&#39; visitor&#39; (方法getVisitor())将被调用。此方法返回的值将用于使用名称&#39; visitor&#39;填充会话。

现在,访客&#39;由于它的价值已经在HttpSession中,让我们考虑以下安排:

@Controller
@SessionAttributes("visitor")
@RequestMapping("/trades")
public class TradeController {

    @RequestMapping("/**")
    public String handleRequestById (@ModelAttribute("visitor") Visitor visitor,
                                     Model model,
                                     HttpServletRequest request) {
        model.addAttribute("msg", "trades request, serving page " +
                                                 request.getRequestURI());
        visitor.addPageVisited(request.getRequestURI());
        return "traders-page";
    }
   .......
}

在目标处理程序方法中找到@ModelAttribute(&#34; visitor&#34;)后,Spring将检索&#39; visitor&#39;从会话中将值分配给Visitor参数,并将调用该方法。在这一步,Spring并不关心如何使用访问者来填充会话,无论是使用最后一种安排还是其他方式填充,它都不重要,Spring只需要注释@SessionAttributes(&#39; visitor&#39;),带有@ModelAttribute(&#34; visitor&#34;)的处理程序方法参数以及&#39; visitor&#39;的值。在HttpSession中。如果spring无法在会话中找到并且最后一个安排不可用,那么将抛出以下异常:

org.springframework.web.HttpSessionRequiredException:预期的会话属性&#39;访客&#39;

换句话说:当在给定会话中第一次调用目标处理程序方法时,调用带有@ModelAttribute(&#39; visitor)的方法,返回的值填充在HttpSession中,并且处理程序方法具有相同的处理方法调用值。对于同一HTTPSession中的后续请求,Spring从会话中检索相同的对象,并且不再使用@ModelAttribute(&#39; visitor&#39;)再次调用该方法,直到会话结束

以下是完整的控制器类:

@Controller
@SessionAttributes("visitor")
@RequestMapping("/trades")
public class TradeController {

    @RequestMapping("/**")
    public String handleRequestById (@ModelAttribute("visitor") Visitor visitor,
                                     Model model,
                                     HttpServletRequest request) {
        model.addAttribute("msg", "trades request, serving page " +
                                                 request.getRequestURI());
        visitor.addPageVisited(request.getRequestURI());
        return "traders-page";
    }

    @ModelAttribute("visitor")
    public Visitor getVisitor (HttpServletRequest request) {
        return new Visitor(request.getRemoteAddr());
    }
}

在上面的示例中,我们正在跟踪同一HTTP会话中的用户访问页面。我们正在使用通配符&#39; / **&#39;以便所有请求以&#39;交易开始将映射到此控制器。

答案 3 :(得分:-2)

将会话注入控制器类,将对象存储在那里并在需要时使用它,例如:

@Controller
public class SomeController {

  //@Autowired
  //private HttpSession session; This is not desired. See the discussion in the 
  //comments.

  @RequestMapping("somePathName")
  public String someHandler(HttpSession session) { //Session will be injected by 
    //Spring without any additional annotations.
    //...
    session.setAttribute("category", yourObject);
  }
}

如果您需要在category以外的其他网页上访问admin/addproduct,则需要将其添加到相应的模型中,如下所示:

@RequestMapping("somePathName")
public String someHandler(Model model) {
  //...
  model.addAttribute("category", yourObject);
  //...
  return "yourPageName";
}

更新:根据ALex的评论,由于线程安全问题,我不希望将HttpSession实例注入strongly字段{{1}}。我已经分别更改了源代码。