Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在SpringMVC中维护会话?_Java_Spring_Session_Spring Mvc - Fatal编程技术网

Java 如何在SpringMVC中维护会话?

Java 如何在SpringMVC中维护会话?,java,spring,session,spring-mvc,Java,Spring,Session,Spring Mvc,使用SpringMVC,我需要将我的对象存储到会话中,并且我应该使用jstl在几个jsp页面中使用相同的对象。我试过这样做: ModelAndView modelAndView = new ModelAndView("admin/addproduct", "category", categorynameList); 但是除了addproductpage之外,我无法访问其他jsp页面的类别 如何才能做到这一点?将会话注入控制器类,将对象存储在那里,并在需要时使用它,例如: @Controller

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

ModelAndView modelAndView = new ModelAndView("admin/addproduct", "category", categorynameList);
但是除了
addproduct
page之外,我无法访问其他jsp页面的类别


如何才能做到这一点?

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

@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);
  }
}
如果您需要访问除
admin/addproduct
之外的其他页面上的
category
,则需要将其添加到相应的型号中,如下所示:

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

更新:根据ALex的评论,由于线程安全问题,将
HttpSession
实例注入字段是
强烈的
不需要的,我已分别更改了源代码。

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

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

SpringMVC提供了多种机制,可以对您隐藏对HttpSession的简单使用

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


此外,您可以在应用程序上下文中将bean定义为会话作用域,然后使用ScopedProxyFactoryBean(只需在bean定义中添加
元素),从而能够将该bean注入到单例控制器中。

注释@SessionAttributes在类级别上使用。通常它用于@Controller类。它的“value”元素的类型为String[],其值是@modeldattribute在方法级别或处理程序的方法参数级别上使用的匹配名称

我们考虑以下安排:

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

    @ModelAttribute("visitor")
    public Visitor getVisitor (....) {
        return new 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";
    }
   .......
}
在上面的代码中,当请求传入时,Spring将做的第一件事是注意@SessionAttributes('visitor'),然后尝试在javax.servlet.http.HttpSession中查找'visitor'的值。如果找不到该值,则将调用@modeldattribute具有相同名称“visitor”(方法getVisitor())的方法。此方法返回的值将用于使用名称“visitor”填充会话

<>现在,它的值“访问者”已经在HtpStip中,我们考虑以下安排:

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

    @ModelAttribute("visitor")
    public Visitor getVisitor (....) {
        return new 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”)时,Spring将从会话中检索“visitor”的值,并将该值分配给visitor参数并调用该方法。在这一步中,Spring不关心会话是如何填充“visitor”的,不管它是使用最后一种安排还是其他方式填充的,这无关紧要,Spring只需要注释@SessionAttributes('visitor')、带有@ModelAttribute(“visitor”)的handler方法参数和HttpSession中的“visitor”值。如果spring在会话中找不到它,并且最后的安排不可用,则将引发以下异常:

org.springframework.web.HttpSessionRequiredException:预期的会话属性为“访问者”

换句话说:当在给定会话中第一次调用目标处理程序方法时,然后调用带有@modeldattribute('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”开头的请求都将映射到此控制器。

恐怕@SessionAttributes是为了在一个特定处理程序的请求之间保留数据,仅在该处理程序的生命周期内。文档中说“特定处理程序使用的会话属性”。看你是对的;谢谢我将编辑我的答案来指出这一点。我不推荐这种方法。控制器在请求之间重用,因此不应具有状态。将其注入到特定的控制器方法中。注入到字段和方法之间有什么区别?从功能上讲,这不会改变任何东西,但在第一种情况下,您需要编写的内容会更少。如果控制器是单例(默认情况下是单例),并且您将会话存储在私有变量中,那么所有用户的所有请求都可以使用它。您希望访问请求范围内的特定用户会话,即对控制器方法的单个调用的范围。会话在请求范围内没有意义。此外,每个用户只能访问自己的会话。会话在请求范围内是有意义的。您可以从HttpServletRequest访问会话。(欢迎(最后)在SO上发布!)您将看到代码片段非常突出(被
`
“backticks”包围)-如果可能出现歧义,请执行相同的操作(或在任何地方都执行一致性操作-说到这一点:使用Java字符串分隔符
围绕Java
String
literals)。