`
bugyun
  • 浏览: 543275 次
社区版块
存档分类
最新评论

Spring MVC中Session的正确用法(转)

 
阅读更多

 

转自:http://www.cnblogs.com/waytofall/p/3460533.html

 

Spring MVC是个非常优秀的框架,其优秀之处继承自Spring本身依赖注入(Dependency Injection)的强大的模块化和可配置性,其设计处处透露着易用性、可复用性与易集成性。优良的设计模式遍及各处,使得其框架虽然学习曲线陡峭,但一旦掌握则欲罢不能。初学者并不需要过多了解框架的实现原理,随便搜一下如何使用“基于注解的controller”就能很快上手,而一些书籍诸如“spring in action”也给上手提供了非常优良的选择。

网上的帖子多如牛毛,中文的快速上手,英文的深入浅出。这样看来,Spring的学习简直是一个轻松愉快的过程。

但是!!

关于Spring中session的使用,大部分资料都讳莫如深。也许这个问题太过容易推断出?大部分资料都没有包括我下面所将要陈述的内容。关于Spring中session的正确使用方法,这里甚至建议直接使用HttpSession。但这种方法显然违背了Spring “technology agnostic” (这个名词我理解意思就是无论你是在什么具体的应用中使用类似的控制逻辑,servlet、一个本地JVM程序或者其他,你的Controller都可以得到复用)的初衷。

于是我开始从庞大的网络资源和书籍中搜索关于Session的正确用法及Spring MVC处理Session的机制,其中讲得最深入而且清楚的算是这一篇。从上文的内容,及我所查阅的比如官方文档这种资料中,我可以大约推断出几个要点:

1. Spring框架会在调用完Controller之后、渲染View之前检查Model的信息,并把@SessionAttributes()注释标明的属性加入session中

2. @ModelAttribute在声明Controller的参数的时候,可以用来表明此参数引用某个存在在Model中的对象,如果这个对象已经存在于Model中的话(Model可以在调用Controller之前就已经保存有数据,这应该不仅仅因为HandlerInterceptor或者@ModelAttribute标记的方法已经显式的将一些对象加入到了Model对象中,也因为Spring会默认将一些对象加入到Model中,这一点很重要)。

3. 如果Session中已经存在某个对象,那么可以直接使用ModelAttribute声明Controller的参数,在Controller中可以直接使用它。

其中1很明确,我提到的那篇文章主要就在说明这一点。而从2和3我们也许可以大胆地推出一个结论:

    Spring会在调用Controller之前将session中的对象填入Model

因为想从2得到3,这个结论就显得比较自然。那么事实上是不是如此呢?可以做一个小实验。仿效我所引用的那篇文章,我写了如下代码:

复制代码
@Controller
@RequestMapping("/user")
@SessionAttributes("userId")
public class UserController {
    
    @RequestMapping(value="/login", method=GET)
    public String login (
            int id, Model model, HttpServletRequest request, HttpSession session) {
        
        model.addAttribute("userId", id);
        
        System.out.println("");
        System.out.println("");
        System.out.println("inside login");
        
        System.out.println("");
        System.out.println("--- Model data ---");
        Map modelMap = model.asMap();
        for (Object modelKey : modelMap.keySet()) {
            Object modelValue = modelMap.get(modelKey);
            System.out.println(modelKey + " -- " + modelValue);
        }

        System.out.println("");
        System.out.println("*** Session data ***");
        Enumeration<String> e = session.getAttributeNames();
        while (e.hasMoreElements()) {
            String s = e.nextElement();
            System.out.println(s + " == " + session.getAttribute(s));
        }

        return "/test";
    }
    
    @RequestMapping(value="/check", method=GET)
    public String check (
            Model model, HttpServletRequest request, HttpSession session) {
        
        System.out.println("");
        System.out.println("");
        System.out.println("inside check");
        
        System.out.println("");
        System.out.println("--- Model data ---");
        Map modelMap = model.asMap();
        for (Object modelKey : modelMap.keySet()) {
            Object modelValue = modelMap.get(modelKey);
            System.out.println(modelKey + " -- " + modelValue);
        }
        
        System.out.println("");
        System.out.println("*** Session data ***");
        Enumeration<String> e = session.getAttributeNames();
        while (e.hasMoreElements()) {
            String s = e.nextElement();
            System.out.println(s + " == " + session.getAttribute(s));
        }

        return "/test";
    }
}
复制代码

而test.jsp的作用就是把Session中的对象打印出来。

调用的顺序是,在首先保证Session为空的情况下,先后输入以下链接:

http://localhost:8080/XX/user/check

http://localhost:8080/XX/user/login?id=1

http://localhost:8080/XX/user/check

页面的显示结果分别为:

1

2

3

 

而Tomcat的输出结果为:

 

inside check

--- Model data ---

*** Session data ***


inside login

--- Model data ---
userId -- 1

*** Session data ***


inside check

--- Model data ---
userId -- 1

*** Session data ***
userId == 1

 

结果如我所料。首先Session中并没有userId属性,在某个Controller加入了它之后,随后的Controller中的Model会自动加入已经存在于Session的对象。虽然确实有很多很多帖子提到了@SessionAttributes并不是使用session的正确方法,但是如实验所得,使用它使得最终属性都加入到了HttpSession对象中,夫复何求?(这里也许需要更多的讨论,我倒希望能有什么更值得信服的说法让我乖乖用回HttpSession)。那么,在Spring中使用Session的一个相对比较“technology agnostic”的方法就是:

1 使用@SessionAttributes提示框架哪些属性需要存在Session中

2 在某些Controller中将这些属性加入到Model中

3 在另外一些Controler中直接使用这些属性

4 在其他Controller中判断Model中是否存在相应属性,以确定Session中是否已经注册了这个属性

分享到:
评论

相关推荐

    Spring mvc 分步式session的实例详解

    主要介绍了Spring mvc 分步式session的实例详解的相关资料,这里举例说明该如何使用spring mvc 分不式的实例,希望能帮助到大家,需要的朋友可以参考下

    Spring-Reference_zh_CN(Spring中文参考手册)

    6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来...

    Spring MVC中自带的跨域问题解决方法

    就是我的前端和后端是放在不同的服务器上的,然后使用opst请求的时候报错,所以通过查找相关的资料终于解决了,下面这篇文章主要给大家介绍了关于Spring MVC中自带的跨域问题解决方法的相关资料,需要的朋友可以参考...

    Spring中文帮助文档

    6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...

    spring-webmvc-jwt-sample:使用Spring Security和基于JWT令牌的身份验证来保护REST API

    Spring Session(具有Spring Security)提供了一种简单的策略来创建和验证基于标头的令牌(会话ID),它可用于保护RESTful API,我已经在我的和进行了演示。 除了这些,Spring Security OAuth(Spring Security的子...

    spring security 参考手册中文版

    12.2.3使用RequestPostProcessor在Spring MVC测试中以用户身份运行 106 作为用户在Spring MVC测试中使用注释运行 108 12.2.4测试HTTP基本认证 109 12.3 SecurityMockMvcRequestBuilders 109 12.3.1测试基于表单的...

    Spring 2.0 开发参考手册

    6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. ...

    springboot学习思维笔记.xmind

    Spring Session Spring项目快速搭建 Maven简介 Maven安装 Maven的pom.xml dependencies dependency 变量定义 编译插件 Spring项目的搭建 Spring Tool Suite ...

    Spring API

    6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...

    spring chm文档

    6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. 其它资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. ...

    spring.doc

    3.3.2使用静态工厂方法实例化(简单工厂模式) 14 3.3.3初始化(创建)bean时机 15 Lazy-init初始化bean的时机拓展: 15 3.4 Bean的作用域 16 Scope单例多例作用域拓展: 16 3.4.1 singleton(默认值) 16 3.4.2 prototype...

    DWZ+springMVC+security+权限+mybatis+postgresql+demo

    我就花了几天的时间制作和部署了初始化系统,完成了login的登录,同时对用户登录和session过期进行安全验证,同时将原有的mybaits改造成了postgre,另外增加了权限的使用方法,由于原来的DWZ的列表增删改查、分页并...

    SpringMVC基础上的web框架

    这个框架是在学习Spring的时候,为了积累学习成果,自己搭建的,一般的系统开发也可以直接使用,包括一个系统开发的基础功能。 以下是当时自己开发时的日志,大致可以说明框架里已有功能 1.0.5 从web项目迁移成maven...

    轻量级java web MVC框架

    一个非常简单的MVC框架,实现了类似Spring MVC的基本功能。 1、包括自动扫描绑定映射路径,只要在web.xml中指定扫描包,系统启动后会将请求url绑定到指定的处理方法上。如: 在web.xml中定义如下: &lt;param-name&gt;...

    springmybatis

    mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in action之八mybatis 动态sql语句 mybatis实战教程mybatis in ...

    Servle和JSP学习指南,完整扫描版

    第5~7章分别阐述JSTL中最重要的类库、标签的具体编写方法和标签文件;第8~10章讨论Servlet中的事件驱动编程、过滤器,以及Model 2架构;第11章展示如何利用Servlet 3的文件上传特性,以及如何在客户端改善用户的体验...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (1)

    6.3 Log4j的使用方法 6.3.1 配置Log4j 6.3.2 配置根Logger 6.3.3 指定日志输出位置 6.3.4 指定日志输出格式 6.3.5 指定日志输出优先级 6.3.6 在代码中使用Log4j 6.4 改进Log4j 6.5 小结 第七章 Ant使用指南 7.1 Ant...

    搞定J2EE:STRUTS+SPRING+HIBERNATE整合详解与典型案例 (3)

    6.3 Log4j的使用方法 6.3.1 配置Log4j 6.3.2 配置根Logger 6.3.3 指定日志输出位置 6.3.4 指定日志输出格式 6.3.5 指定日志输出优先级 6.3.6 在代码中使用Log4j 6.4 改进Log4j 6.5 小结 第七章 Ant使用指南 7.1 Ant...

    Spring面试题

    正如我将在下一个示例中演示的那样,Spring 框架使用 JavaBean 属性和配置数据来指出必须设置的依赖关系。 BeanFactory 接口 因为 org.springframework.beans.factory.BeanFactory 是一个简单接口,所以可以针对...

    浅谈SpringMVC中的session用法及细节记录

    下面小编就为大家带来一篇浅谈SpringMVC中的session用法及细节记录。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

Global site tag (gtag.js) - Google Analytics