使用spring MVC,我需要将我的对象存储到会话中,并且我应该使用jstl在几个jsp页面中使用相同的对象。我试过这样:
ModelAndView modelAndView = new ModelAndView("admin/addproduct", "category", categorynameList);
但是我无法访问除addproduct
page 之外的其他 jsp 页面的类别。
我怎样才能做到这一点?
使用spring MVC,我需要将我的对象存储到会话中,并且我应该使用jstl在几个jsp页面中使用相同的对象。我试过这样:
ModelAndView modelAndView = new ModelAndView("admin/addproduct", "category", categorynameList);
但是我无法访问除addproduct
page 之外的其他 jsp 页面的类别。
我怎样才能做到这一点?
Spring MVC 提供了不止一种机制来隐藏对HttpSession
您的普通使用。
查看@SessionAttributes
注释,它允许您定义将由控制器存储在会话中的属性;此机制主要用于维护您的处理程序的会话状态,并且该状态通常在会话完成后被清除。
此外,您可以将 bean 定义为应用程序上下文中的会话范围,然后使用 ScopedProxyFactoryBean(只需<aop:scoped-proxy/>
在 bean 定义中添加一个元素),从而能够将该 bean 注入您的单例控制器中。
您可以将会话直接传递给任何带注释的控制器方法:
@RequestMapping("somePathName")
public String someHandler(HttpSession session) {
session.setAttribute(...
注释@SessionAttributes 用于类级别。通常它用于@Controller 类。它的 'value' 元素是 String[] 类型,其值是 @ModelAttribute 在方法级别或处理程序的方法参数级别上使用的匹配名称。
让我们考虑以下安排:
@Controller
@SessionAttributes("visitor")
@RequestMapping("/trades")
public class TradeController {
@ModelAttribute("visitor")
public Visitor getVisitor (....) {
return new Visitor(....);
}
....
}
在上面的代码中,当一个请求进来时,Spring首先会注意到@SessionAttributes('visitor'),然后尝试在javax.servlet.http.HttpSession中找到'visitor'的值。如果它没有找到该值,则将调用具有相同名称“访问者”的 @ModelAttribute 方法(方法 getVisitor())。这种方法的返回值将用于填充名称为“访问者”的会话。
现在 'visitor' 的值已经在 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("visitor") 时,Spring 将从会话中检索 'visitor' 的值,并将该值分配给 Visitor 参数并调用该方法。这一步,Spring并不关心session是如何填充'visitor'的,不管是最后的排列方式还是其他方式填充,都无所谓,Spring只需要注解@SessionAttributes('visitor') ,带有@ModelAttribute("visitor")的handler方法参数和HttpSession中'visitor'的值。如果 spring 在 session 中找不到它并且最后的安排不可用,则会抛出以下异常:
org.springframework.web.HttpSessionRequiredException:预期的会话属性“访客”
换句话说:当在给定会话中第一次调用目标处理程序方法时,将调用带有@ModelAttribute('visitor) 的方法,返回值填充到 HttpSession 中,并调用具有相同值的处理程序方法。对于同一个 HTTPSession 中的后续请求,Spring 从会话中检索相同的对象,直到会话结束才再次调用带有 @ModelAttribute('visitor') 的方法
以下是完整的控制器类:
@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 会话中用户访问的页面。我们使用通配符“/**”,以便所有以“trades”开头的请求都将映射到此控制器。
将会话注入您的控制器类,将您的对象存储在那里并在需要时使用它,例如:
@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