深入理解springMVC中的Model和Session属性

目录
  • springMVC的范围
  • spring的@MODELATTRIBUTE
  • spring Model和Request后边的原因
  • Spring的@SESSIONATTRIBUTE
  • 控制对话属性

作为一个javaweb应用的开发者,你快速学习了request(HttpRequest)和Session(HttpSession)的范围,理解这些范围并且在这些范围内数据和对象是如何是进出的对设计和构建web应用是非常关键的。

springMVC的范围

当我用springMVC写web应用的时候,我发现spring model和session有一点神秘—特别是与http reques、和session范围关联起来这些我都已经了解了。

spring的model元素会在我的session或者request中找到吗,如果是这样,我怎么控制这个过程呢,在这篇文章中我希望能够解密springMVC的model和session是如何工作的。

spring的@MODELATTRIBUTE

这里有好几种向spring的Model添加数据的方式。数据或者对象通常通过在controller上的注释方法添加到spring中的model中去。

下边这个例子中,@ModelAttribute用来将MyCommandBean的实例以key值为myRequestObject添加到model中去

@Controller
public class MyController {

 @ModelAttribute("myRequestObject")
 public MyCommandBean addStuffToRequestScope() {
  System.out.println("Inside of addStuffToRequestScope");
  MyCommandBean bean = new MyCommandBean("Hello World",42);
  return bean;
 }

 @RequestMapping("/dosomething")
 public String requestHandlingMethod(Model model, HttpServletRequest request) {
  System.out.println("Inside of dosomething handler method");

  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("=== Request data ===");
  java.util.Enumeration reqEnum = request.getAttributeNames();
  while (reqEnum.hasMoreElements()) {
   String s = reqEnum.nextElement();
   System.out.println(s);
   System.out.println("==" + request.getAttribute(s));
  }

  return "nextpage";
 }

         //  ... the rest of the controller
}

在一个请求的request中,任何使用@ModelAttribute注解的方法会在controller的handler方法(像上边例子汇总的requestHandlingMethod 方法)之前被调用。

在这些handler方法执行前,这些方法把数据增加到java.util.map中最终添加到spring Model中去。这可以通过一个简单的实验证明,我创建了两个jsp页面:index.jsp和nextpage.jsp。

index.jsp中的链接用来发送request到web应用中来触发Mycontroller中的requestHandlingMethod()方法。requestHandlingMethod()方法返回“nextpage”作为下一个视图逻辑上的名字,在这个例子中我们解析为nextpage.jsp。

当这个小的web站点用这种方式执行的时候,controller里边的System.out.println方法表明了@ModelAttribute方法是如何在handler方法之前运行的。

它同样也展示了这个MyCommandBean被创建和添加到springModel中去的过程。

Inside of addStuffToRequestScope
Inside of dosomething handler method
--- Model data ---
myRequestObject -- MyCommandBean [someString=Hello World, someNumber=42]
=== Request data ===
org.springframework.web.servlet.DispatcherServlet.THEME_SOURCE
==WebApplicationContext for namespace 'dispatcher-servlet': startup date [Sun Oct 13 21:40:56 CDT 2013]; root of context hierarchy
org.springframework.web.servlet.DispatcherServlet.THEME_RESOLVER
==org.springframework.web.servlet.theme.FixedThemeResolver@204af48c
org.springframework.web.servlet.DispatcherServlet.CONTEXT
==WebApplicationContext for namespace 'dispatcher-servlet': startup date [Sun Oct 13 21:40:56 CDT 2013]; root of context hierarchy
org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping
==dosomething.request
org.springframework.web.servlet.HandlerMapping.bestMatchingPattern
==/dosomething.*
org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER
==org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@18fd23e4

现在的问题是“springModel数据存储在哪?”它存储在标准的java request范围中吗?答案是“是的”,从上边的输出可以看出,当handler方法执行的时候MyCommandBean是在model中,但是没有在request对象中。

确实,spring不会把model数据作为request的属性,直到执行handler方法之后和下一个视图之前(在这个例子中是nextpage.jsp)

这也可以通过打印存储在index.jsp和nextpage.jsp中的HttpServletRequest中的数据展示出来,这两个页面我都使用jsp来展示HttpServletRequest的属性

Request Scope (key==values)
<%
 java.util.Enumeration<String> reqEnum = request.getAttributeNames();
 while (reqEnum.hasMoreElements()) {
  String s = reqEnum.nextElement();
  out.print(s);
  out.println("==" + request.getAttribute(s));
%><br />
<%
 }
%>

当应用打开并且index.jsp展现的时候,你可以看到在Request范围内没有属性

do something
Request Scope(key==values)

在这个例子中,当“do something”连接被点击的时候触发了MyController的handler方法执行,继而导致nextpage.jsp被执行,考虑到这是同样的jsp内容,再次提出不免有些啰嗦。当nextpage.jsp提出的时候,表明model的MyCommandBean在controller里被创建,并已经被加到HttpServletRequest范围中去了。这个spring model的属性key已经被复制,并且当做Request属性的key。

所以spring model数据的创建要早于handler方法的执行,在下一个视图加载前就已经被复制到HttpServletRequest中去了。

spring Model和Request后边的原因

你可能会疑惑为什么spring使用model属性,为什么不直接将数据加到Request对象中去呢,在Rod Johnson的书中我找到了这个问题的答案。下边就是来自这本书的关于model元素的文本。

直接给HttpServletRequest(或者Request属性)增加元素看起来实现了相同的目的,做这件事的原因很明确,当我们查看我们为MVC框架设置的要求的时候,应该尽可能使视图无关的,意味着视图技术不和HttpServletRequest绑定。

Spring的@SESSIONATTRIBUTE

现在你知道spring的model数据是如何管理的并且是如何和Httprequset属性关联的,那么spring的session数据呢?

spring的@SessionAttributes在controller上使用指定model属性应该存储在Session中。实际上,精确的讲spring开发文档已经表明了@SessionAttributes注解“列出了应该存储在Session中或者对话存储中model属性的名字”。

实际上,@SessionAttribute允许你做的是在加载视图之前,告诉spring你的哪一个model Attributes将会被复制到httpSession中去。

Session Scope (key==values)
<%
  java.util.Enumeration<String> sessEnum = request.getSession()
 .getAttributeNames();
  while (sessEnum.hasMoreElements()) {
 String s = sessEnum.nextElement();
 out.print(s);
 out.println("==" + request.getSession().getAttribute(s));
%><br />
<%
  }
%>

我在MyController中用@SessionAttributes做注解,来把同样的model属性加到spring Session中去。

@Controller
@SessionAttributes("myRequestObject")
public class MyController {
  ...
}

我同样也在handler方法中增加了代码来展示什么属性在httpSession中

@SuppressWarnings("rawtypes")
@RequestMapping("/dosomething")
public String requestHandlingMethod(Model model, HttpServletRequest request, HttpSession session) {
  System.out.println("Inside of dosomething handler method");

  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("=== Request data ===");
  java.util.Enumeration<String> reqEnum = request.getAttributeNames();
  while (reqEnum.hasMoreElements()) {
 String s = reqEnum.nextElement();
 System.out.println(s);
 System.out.println("==" + request.getAttribute(s));
  }

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

现在,当我们使用@SessionAttributes注解后我们可以看到什么在session对象中,包括springMVC处理一个http 请求的前中后的过程里。结果如下,首先是index.jsp展示,我们可以看到在HttpServletRequest和httpSession中都没有属性数据。

do something
Request Scope(key == values)
Session Scope(key == values)

在handler方法执行过程中(HttpServletRequest),你可以看到MyCommandBean被加入到spring model属性中去,但是没有在HttpServletRequest和HttpSession范围中。

但是在handler方法执行之后并且nextpage.jsp被加载,你可以看到model的属性数据确实被作为属性复制到HttpServletRequest和httpSession中。

控制对话属性

现在你已经对spring model和Session属性数据是如何加载到HttpServletReq。uest和httpSession有很好的理解了。但你依旧对管理spring Session中的数据心生疑惑。spring提供了移除spring Session属性的方式,也可以在HttpSession中移除。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringMVC通过模型视图ModelAndView渲染视图的实现

    SpringMVC通过模型视图ModelAndView渲染视图大致流程 代码样例 1.准备工作 A.因为文中用到jsp,所以需要引入jsp标准标签库standard.jar和jstl.jar 官方下载地址:http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ 本地下载地址:lib_jb51.rar B.添加Tomcat依赖如下: <dependency> <groupId>org.springframew

  • SpringMVC中Model与Session的区别说明

    目录 Model与Session区别 流程 小结一下 session和model问题导致登录无法正常退出 问题 分析 Model与Session区别 什么是Session:Session:在计算机中,尤其是在网络应用中,称为"会话".它具体是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间. 在网站使用中,为了保存用户信息.服务器会给每一个用户(浏览器)创建一个Session. 流程 1.客户端请求服务器 2.服务器创建Session,在服

  • SpringMVC中@ModelAttribute注解的使用教程

    前言 @ModelAttribute最主要的作用是将数据添加到模型对象中,用于视图页面展示时使用. @ModelAttribute等价于 model.addAttribute("attributeName", abc); 但是根据@ModelAttribute注释的位置不同,和其他注解组合使用,致使含义有所不同.具体区别如下: 1.@ModelAttribute注释方法 例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方法执行前被

  • SpringMVC执行步骤、Model的使用详解

    目录 第一个SpringMvc HelloWorld 无启动类 前端操作 后台执行步骤 第二个SpringMvc项目 项目简介 知识点整合 代码实例:SpringMvc02 SpringMvc对rest风格url的支持 SpringMvc文件上传 SpringMvc文件上传 图解SpringMvc的执行流程 第一个SpringMvc HelloWorld 无启动类 springboot才有启动类 前端操作 访问项目名进入默认主页,显示一个链接 点击链接后请求helloWorld.do跳转另一个j

  • SpringMVC中重定向model值的获取方式

    目录 SpringMVC重定向model值的获取 1.步骤一:在控制器中编写 2.编写对应跳转 3.测试:在浏览器访问自己项目下的对应控制器 4.然后浏览器跳转 SpringMVC中model的理解 1.首先将数据添加到Model中 2.然后再将其在页面上展示出来 SpringMVC重定向model值的获取 1.步骤一:在控制器中编写 /*重定向测试*/ @RequestMapping("/m1/t2") public String test1(Model model, String

  • SpringMVC中的Model对象用法说明

    模型对象的作用主要是保存数据,可以借助它们将数据带到前端. 常用的模型对象有以下几个: ModelAndView(顾名思义,模型和视图,既可以携带数据信息,也可以携带视图信息,常规用法如下) /** * ModelAndView 绑定数据到视图 (ModelMap用于传递数据 View对象用于跳转) * @return * @throws Exception */ @RequestMapping(value="/case2") public ModelAndView case2() t

  • 深入理解springMVC中的Model和Session属性

    目录 springMVC的范围 spring的@MODELATTRIBUTE spring Model和Request后边的原因 Spring的@SESSIONATTRIBUTE 控制对话属性 作为一个javaweb应用的开发者,你快速学习了request(HttpRequest)和Session(HttpSession)的范围,理解这些范围并且在这些范围内数据和对象是如何是进出的对设计和构建web应用是非常关键的. springMVC的范围 当我用springMVC写web应用的时候,我发现s

  • 如何理解SpringMVC

    目录 一.SpringMVC简介 二.SpringMVC核心组件 2.1.DispatcherServlet 2.2.HandlerMapping 2.3.HandlerInterceptor 2.4.HandlerExecutionChain 2.5.HandlerAdapter 2.6.Handler 2.7.ModelAndView 2.8.ViewResolver 2.9.View 三.配置Maven环境变量 3.1.Maven介绍 3.2.Maven下载安装 3.2.1.Maven下载

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

    前言 初学SpringMVC,最近在给公司做的系统做登录方面,需要用到session. 在网上找了不少资料,大致提了2点session保存方式: 1.javaWeb工程通用的HttpSession 2.SpringMVC特有的@SessionAttributes 我个人比较关注@SessionAttributes的用法,毕竟现在是在用SpringMVC嘛.但是我看网上那些文章,基本都是只说明了基础用法,详细的使用和细节却基本没有,我想这是不够的,所以我自己做了一些测试,然后整理了下代码做了个de

  • SpringMVC中Model和ModelAndView的EL表达式取值方法

    model和modelMap(spring 封装),Java.util.Map ModelMap(视图) ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("name", "xxx"); modelAndView.setViewName("/user/index"); return modelAndView; //对于ModelAndView构造函数可以指

  • SpringMVC中RequestParam注解的简单理解

    目录 1.前言 2.name/value属性 3.required属性 4.defaultValue属性 总结 1.前言 作用:主要用于对前端请求的参数进行一些约束,包括参数名不匹配问题.是否必须.默认值! 这个注解非常简单,准确的说应该是MVC中除了Controller之外最简单的注解. @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Request

  • 深入理解PHP中的Session和Cookie

    在一个页面设置一个cookie时,必须刷新或到下一个页面才可以用 $_COOKIE 得到变量的值.原因是因为当页面第一次被浏览器访问载入时,页面中的 cookie 会被设置,将其发送存储到客户端指定的存储位置,所以$_COOKIE没有接收到客户端发送过来的 cookie 变量的值,当刷新或到下一个页面时,客户端会在页面程序在服务器端运行之前,发送与该地址相对应的 cookie到服务器端,所以 $_COOKIE 可以得到的值! 说白了就是当每一个页面被访问时,如果客户端找到了与访问地址相对应的 c

  • 详解SpringMVC中使用Interceptor拦截器

    SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间.  一.定义Interceptor实现类 SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的.在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interce

随机推荐