如何在Spring-MVC中使用会话属性


108

您能帮我写这段代码的Spring MVC风格模拟吗?

 session.setAttribute("name","value");

以及如何在@ModelAttribute会话中添加带有注释的元素,然后对其进行访问?

Answers:


185

如果您想在每次响应后删除对象,则不需要会话,

如果要在用户会话期间保留对象,可以采用以下几种方法:

  1. 直接向会话添加一个属性:

    @RequestMapping(method = RequestMethod.GET)
    public String testMestod(HttpServletRequest request){
       ShoppingCart cart = (ShoppingCart)request.getSession().setAttribute("cart",value);
       return "testJsp";
    }
    

    你可以像这样从控制器获取它:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. 使您的控制器会话范围

    @Controller
    @Scope("session")
    
  3. 作用域对象,例如,您有应该在每次会话中使用的用户对象:

    @Component
    @Scope("session")
    public class User
     {
        String user;
        /*  setter getter*/
      }
    

    然后在所需的每个控制器中注入类

       @Autowired
       private User user
    

    保持课堂上的会话。

  4. AOP代理注入:在spring -xml中:

    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
      <bean id="user"    class="com.User" scope="session">     
          <aop:scoped-proxy/>
      </bean>
    </beans>
    

    然后在所需的每个控制器中注入类

    @Autowired
    private User user
    

5.将HttpSession传递给方法:

 String index(HttpSession session) {
            session.setAttribute("mySessionAttribute", "someValue");
            return "index";
        }

6.通过@SessionAttributes(“ ShoppingCart”)在会话中创建ModelAttribute:

  public String index (@ModelAttribute("ShoppingCart") ShoppingCart shoppingCart, SessionStatus sessionStatus) {
//Spring V4
//you can modify session status  by sessionStatus.setComplete();
}

或者您可以将模型添加到整个Controller类,例如,

@Controller
    @SessionAttributes("ShoppingCart")
    @RequestMapping("/req")
    public class MYController {

        @ModelAttribute("ShoppingCart")
        public Visitor getShopCart (....) {
            return new ShoppingCart(....); //get From DB Or Session
        }  
      }

每个人都有优点和缺点:

@session可能会在云系统中使用更多的内存,它将会话复制到所有节点,并且直接方法(1和5)具有混乱的方法,对单元测试不利。

访问会话jsp

<%=session.getAttribute("ShoppingCart.prop")%>

在Jstl中:

<c:out value="${sessionScope.ShoppingCart.prop}"/>

在Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>

6
3.如果您的控制器是单例的,则需要为具有会话范围的注入组件定义proxyMode = ScopedProxyMode.TARGET_CLASS。@Scope(value =“ session”,proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov

1
尽管首先看起来简单易用,但使控制器会话成为作用域是最糟糕的选择。但是,如果您想在将来的某个时间扩展应用程序,则会遇到麻烦,因为您可能需要像Redis这样的分布式会话存储(除非您使用粘性会话,为了便利而牺牲可用性)。因此,会话范围的bean通常应该是哑的可序列化的POJO。这样,您就可以在需要时进行横向扩展。
克里斯(Chris)2007年

那RequestContextHolder呢?
user1589188

User仅当在类中调用Bean时,注入Bean才有效session,否则,如果没有会话存在,则抛出异常,因为当我们在user另一个类中注入Bean 时,上下文@runtime中不会有任何活动会话!!
Jose Mhlanga

41

@SessionAttributes

请参阅文档:使用@SessionAttributes在请求之间的HTTP会话中存储模型属性

了解Spring MVC模型和会话属性 ”还对Spring MVC会话进行了很好的概述,并说明了如何/何时@ModelAttribute将其传输到会话中(如果对控制器进行了@SessionAttributes注释)。

该文章还解释说,最好@SessionAttributes在模型上使用,而不是直接在HttpSession上设置属性,因为这样可以帮助Spring MVC保持视图不可知。


如何利用sessionAttributes在Controller之间传输对象?
larrytech '16

27

SessionAttribute注释是最简单直接的方法,而不是从请求对象和设置属性获取会话。 可以将任何对象添加到控制器中的模型,如果其名称与@SessionAttributes注释中的参数匹配,则它将存储在会话中。 例如,在下面的personObj会话中。

@Controller
@SessionAttributes("personObj")
public class PersonController {

    @RequestMapping(value="/person-form")
    public ModelAndView personPage() {
        return new ModelAndView("person-page", "person-entity", new Person());
    }

    @RequestMapping(value="/process-person")
    public ModelAndView processPerson(@ModelAttribute Person person) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("person-result-page");

        modelAndView.addObject("pers", person);
        modelAndView.addObject("personObj", person);

        return modelAndView;
    }

}

会话仅适用于同一控制器实例中的请求。如果需要将控制权发送到另一个控制器,该会话将被销毁,并在必要时创建一个新会话。
larrytech '16

1
@larrytech怎么可能?我认为您刚刚忘记将SessionAttributes添加到第二个控制器
Yura,2016年

19

以下带注释的代码会将“值”设置为“名称”

@RequestMapping("/testing")
@Controller
public class TestController {
@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
    request.getSession().setAttribute("name", "value");
    return "testJsp";
  }
}

要在JSP中使用,请使用 ${sessionScope.name}

对于@ModelAttribute看到这个链接


4

这不是最简单的吗 最短吗?我知道它并进行了测试-在这里可以完美地工作:

@GetMapping
public String hello(HttpSession session) {
    session.setAttribute("name","value");
    return "hello";
}

ps 我来这里是为了寻找答案“ 如何在Spring-mvc中使用Session属性,但是读了那么多却没有看到我在代码中写的最明显的内容。我没有看到它,所以我认为它是错误的,但事实并非如此。因此,让我们以最简单的解决方案来分享主要问题的知识。


1
你是对的 !这就是我的想法,因为您可以在控制器方法(GET / POST请求)中声明它们时直接访问我们需要的所有Http对象
Shessuky

1

试试这个...

@Controller
@RequestMapping("/owners/{ownerId}/pets/{petId}/edit")
@SessionAttributes("pet")
public class EditPetForm {

    @ModelAttribute("types")

    public Collection<PetType> populatePetTypes() {
        return this.clinic.getPetTypes();
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processSubmit(@ModelAttribute("pet") Pet pet, 
            BindingResult result, SessionStatus status) {
        new PetValidator().validate(pet, result);
        if (result.hasErrors()) {
            return "petForm";
        }else {
            this.clinic.storePet(pet);
            status.setComplete();
            return "redirect:owner.do?ownerId="
                + pet.getOwner().getId();
        }
    }
}

0

当我尝试登录时(这是一种引导模式),我使用了@sessionattributes批注。但是问题在于,当视图是重定向(“ redirect:/ home”)时,我输入到会话中的值会显示在url中。一些Internet资源建议遵循http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting,但我改用了HttpSession。在关闭浏览器之前,该会话将一直存在。这是示例代码

        @RequestMapping(value = "/login")
        @ResponseBody
        public BooleanResponse login(HttpSession session,HttpServletRequest request){
            //HttpServletRequest used to take data to the controller
            String username = request.getParameter("username");
            String password = request.getParameter("password");

           //Here you set your values to the session
           session.setAttribute("username", username);
           session.setAttribute("email", email);

          //your code goes here
}

您无需更改视图方面的特定内容。

<c:out value="${username}"></c:out>
<c:out value="${email}"></c:out>

登录后,将上述代码添加到您网站的任何位置。如果正确设置了会话,则将在其中看到值。确保您正确添加了jstl标记和El-表达式(此处是设置jstl标记的链接https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project-正确/


0

使用此方法非常简单易用

HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getNativeRequest();

                                                            request.getSession().setAttribute("errorMsg", "your massage");

在jsp中使用一次,然后删除

<c:remove var="errorMsg" scope="session"/>      

0

在Spring 4 Web MVC中。您可以在控制器级别@SessionAttribute的方法中使用@SessionAttributes

@Controller
@SessionAttributes("SessionKey")
public class OrderController extends BaseController {

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.