如何在 Spring-mvc 中使用 Session 属性

Posted

技术标签:

【中文标题】如何在 Spring-mvc 中使用 Session 属性【英文标题】:How to use Session attributes in Spring-mvc 【发布时间】:2013-09-18 10:56:37 【问题描述】:

你能帮我写这段代码的spring mvc风格的模拟吗?

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

以及如何将一个被@ModelAttribute注解的元素添加到会话中,然后访问它?

【问题讨论】:

【参考方案1】:

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

如果您想在用户会话期间保留对象, 有几种方法:

    直接给session增加一个属性:

    @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");
    

    使您的控制器会话范围

    @Controller
    @Scope("session")
    

    范围对象,例如您有每次都应该在会话中的用户对象:

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

    然后在你想要的每个控制器中注入类

       @Autowired
       private User user
    

    让课堂保持在会话中。

    AOP 代理注入: 在春天-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
    @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"/>

在百里香中:

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

【讨论】:

3.如果您的控制器是单例的,那么您需要为具有会话范围的注入组件定义 proxyMode = ScopedProxyMode.TARGET_CLASS。 @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) 使控制器会话作用域是这里最糟糕的选择,尽管它起初看起来简单易用。但是,如果您想在未来某个时间扩展您的应用程序,您将遇到麻烦,因为您可能需要像 Redis 这样的分布式会话存储(除非您使用粘性会话,为了方便而牺牲可用性)。因此,会话范围的 bean 通常应该是哑可序列化 POJO。这样,您就可以在需要时进行横向扩展。 RequestContextHolder 呢? 注入User bean 仅当您在同样为session 作用域的类中调用bean 时才有效,否则如果不存在会话,则会抛出异常,因为不会有任何活动当我们将user bean 注入另一个类时,上下文@runtime 中的会话!!【参考方案2】:

试试这个...

@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();
        
    

【讨论】:

【参考方案3】:

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

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

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) 
     // method body

【讨论】:

【参考方案4】:

使用这个方法很简单好用

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

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

在 jsp 中使用一次然后删除

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

【讨论】:

【参考方案5】:

这不是最简单和最短吗?我知道并且刚刚对其进行了测试 - 在这里完美运行:

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

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

【讨论】:

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

当我尝试登录时(这是一个引导模式),我使用了 @sessionattributes 注释。但问题是当视图是重定向(“redirect:/home”)时,我输入到会话中的值会显示在 url 中。一些互联网资源建议关注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-correctly/)

【讨论】:

【参考方案7】:

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 怎么可能?我认为您刚刚忘记将 SessionAttributes 添加到您的第二个控制器【参考方案8】:

使用@SessionAttributes

查看文档:Using @SessionAttributes to store model attributes in the HTTP session between requests

“Understanding Spring MVC Model And Session Attributes”还很好地概述了 Spring MVC 会话,并解释了 @ModelAttributes 是如何/何时转移到会话中的(如果控制器是 @SessionAttributes 注释的)。

那篇文章还解释说,最好在模型上使用@SessionAttributes,而不是直接在 HttpSession 上设置属性,因为这有助于 Spring MVC 与视图无关。

【讨论】:

如何利用 sessionAttributes 在 Controller 之间传输对象?【参考方案9】:

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

@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,请参阅此link

【讨论】:

以上是关于如何在 Spring-mvc 中使用 Session 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring-MVC 中添加“必需”属性 [重复]

如何在 Spring-MVC 中将数据从视图传递到控制器?

如何在 spring-mvc 中将日志记录添加到 webflux 端点?

如何在没有 if else 的情况下处理 Spring-MVC 项目中的错误?

如何在 spring-mvc 中为 REST 查询提供对象列表?

在 Spring-MVC 控制器中触发 404?