spring mvc 5.0 模型视图详解 07

来源:互联网 发布:网络密匙 编辑:程序博客网 时间:2024/05/23 13:34

Spring MVC 提供了以下几种途径输出模型数据:

  1. ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
  2. Map 及 Model: 入参为org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
  3. @SessionAttributes: 将模型中的某个属性暂存到 HttpSession 中,以便多个请求之间可以共享这个属性
  4. @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中

    ModelAndView

控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。
SpringMVC 会把 ModelAndView 的 model 中数据放入到 request 域对象中.
添加模型数据:
   MoelAndView addObject(String attributeName, Object attributeValue)
   ModelAndView addAllObject(Map<String, ?> modelMap)
设置视图:
   void setView(View view )

   void setViewName(String viewName)

package com.ruge.mvc;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import java.util.Date;@Controllerpublic class demo01 {    @RequestMapping(value = "/hello")    public ModelAndView hello1(){        ModelAndView modelAndView = new ModelAndView();        modelAndView.setViewName("SUCCESS");        modelAndView.addObject("time", new Date());        return modelAndView;    }}
<%--  Created by IntelliJ IDEA.  User: Administrator  Date: 2017/12/19 0019  Time: 20:00  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><br><head>    <title>Title</title></head>${time}</br></body></html>

Map及Model

Spring MVC 在内部使用了一个org.springframework.ui.Model 接口存储模型数据

具体步骤
Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。
如果方法的入参为 Map 或 Model 类型,Spring MVC 会将隐含模型的引用传递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据

Controller

package com.ruge.mvc;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import java.util.ArrayList;import java.util.List;import java.util.Map;@Controllerpublic class demo01 {    @RequestMapping(value = "/hello")    public String hello1(Map<String,Object> map){        List list = new ArrayList();        for (int i = 0; i <100 ; i++) {            list.add(i);        }        map.put("list",list);        return "SUCCESS";    }}

jsp

<%--  Created by IntelliJ IDEA.  User: Administrator  Date: 2017/12/19 0019  Time: 20:00  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><br><head>    <title>Title</title></head>${list}</br></body></html>


@SessionAttributes

若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC 将在模型中对应的属性暂存到 HttpSession 中。

@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中
  @SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。
  @SessionAttributes(value={“user1”, “user2”}) 
  @SessionAttributes(types={User.class, Dept.class}) 
  @SessionAttributes(value={“user1”, “user2”}, types={Dept.class})

Controller

package com.ruge.mvc;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.SessionAttributes;import java.util.Map;@SessionAttributes(value = "user")@Controllerpublic class demo01 {   private String userName;   private String passWord;    public String getUserName() {        return userName;    }    public void setUserName(String userName) {        this.userName = userName;    }    public String getPassWord() {        return passWord;    }    public void setPassWord(String passWord) {        this.passWord = passWord;    }    @RequestMapping(value = "/hello")    public String hello1(Map<String,Object> map){        demo01 demo01 = new demo01();        demo01.setUserName("刘德华");        demo01.setPassWord("123456");        map.put("user",demo01);        return "SUCCESS";    }}

Jsp

<%--  Created by IntelliJ IDEA.  User: Administrator  Date: 2017/12/19 0019  Time: 20:00  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><br><head>    <title>Title</title></head>${user.userName}</br>${user.passWord}</br></body></html>


@ModelAttribute

在方法定义上使用 @ModelAttribute 注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
在方法的入参前使用@ModelAttribute 注解:

可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数 绑定到对象中,再传入入参将方法入参对象添加到模型中

Controller

package com.ruge.mvc;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;@Controllerpublic class demo01 {   private String id;   private String userName;   private String passWord;    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getUserName() {        return userName;    }    public void setUserName(String userName) {        this.userName = userName;    }    public String getPassWord() {        return passWord;    }    public void setPassWord(String passWord) {        this.passWord = passWord;    }    @RequestMapping(value = "/hello")    public String hello1(demo01 demo01){        System.out.println("修改id"+demo01.id);        System.out.println("修改userName"+demo01.userName);        System.out.println("修改passWord"+demo01.passWord);        return "SUCCESS";    }}


SUCCESS.jsp

<%--  Created by IntelliJ IDEA.  User: Administrator  Date: 2017/12/19 0019  Time: 20:00  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><br><head>    <title>Title</title></head><!--模拟修改操作1. 原始数据为: 1,Jack,Jack@163.com2. 将username和email修改为Mike、Mike@qq.com,id不能被修改.3. 表单回显, 模拟操作直接在表单填写对应的属性值--><form action="hello" method="Post">    username: <input type="text" name="id" value="123"/>    <br>    username: <input type="text" name="userName" value="Jack"/>    <br>    password: <input type="text" name="passWord" value="123456"/>    <br>    <input type="submit" value="Submit"/></form></body></html>

SpringMVC 确定目标方法 POJO 类型入参的过程

  1. 确定一个 key:

    1). 若目标方法的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写
    2). 若使用了  @ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值. 
  2. 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入
    1). 若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 1 确定的 key 一致, 则会获取到. 
  3. 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰, 若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常. 
  4. 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数
  5. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.

由@SessionAttributes引发的异常

如果在处理类定义处标注了@SessionAttributes(“xxx”),则尝试从会话中获取该属性,并将其赋给该入参,然后再用请求消息填充该入参对象。如果在会话中找不到对应的属性,则抛出 HttpSessionRequiredException 异常