2-SpringMVC-1-模型和视图

1、SpringMVC的概述:

• Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一
• Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架
• Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。
• 支持 REST 风格的 URL 请求
• 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性

2、第一个Hellow

1、步骤:

– 加入 jar 包 – 在 web.xml 中配置 DispatcherServlet
– 加入 Spring MVC 的配置文件
– 编写处理请求的处理器,并标识为处理器
– 编写视图

1.1、jar包:


image.png

1.2、配置 web.xml,spring-mvc.xml:
1.2.1、配置 DispatcherServlet(web.xml) :

DispatcherServlet 默认加载 /WEB-INF/.xml 的 Spring 配置文件, 启动 WEB 层 的 Spring 容器。可以通过 contextConfigLocation 初始化参数自定义配置文件的位置和名称


        springmvc
        org.springframework.web.servlet.DispatcherServlet
        
        
    

    
        springmvc
        *.action
    

配置详解:


image.png

1.2.2、配置自动扫描的包(spring-mvc.xml):

    
    

名称空间补充:

image.png
image.png

1.2.3、配置视图解析器:

视图名称解析器:将视图逻辑名解析为: /WEB-INF/pages/.jsp

    
    
        
        
    

1.3、创建请求处理器类:

@Controller//此注解将类标记为控制层
public class HelloWorld {
    @RequestMapping("/hello")//此注解可映射方法或者类为url
    public String hello() {
        System.out.println ("helloworld...");
        return "success";
    }
}

对应的view:


image.png

1.4、手绘流程图:


手绘hello流程png.png

3、@RequestMapping 映射请求

1.1、概述:

1、 Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求
2、 在控制器的类定义及方法定义处都可标注 :
@RequestMapping
– 类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
– 方法处:提供进一步的细分映射信息。相对于类定义处的 URL。
若类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于WEB 应用的根目录
3、 DispatcherServlet 截获请求后,就通过控制器上
@RequestMapping 提供的映射信息确定请求所对应的处理方法。

2、使用@RequestMappiing示例:

@Controller//此注解将类标记为控制层
@RequestMapping("/hello")//限定所有请求,部署的根路径
public class HelloWorld {
    @RequestMapping("/SpringMVC")//可定义多个方法,加上注解来处理
    public String hello() {
        System.out.println ("helloworld...");
        return "success";
    }
}

3、映射请求参数、请求方法或请求头:

3.1、标准的请求头:


image.png

3.2、@RequestMapping 除了可以使用请求 URL 映射请求外,还可以使用请求方法、请求参数及请求头映射请求
3.3、@RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可让请求映射更加精确化。
3.4、params 和 headers支持简单的表达式:


image.png
能进入的访问地址:http://localhost:8081/mvc/testParamsAndHeaders?username&age=1    (请求头Accept-Language=en-US,zh;q=0.8)

    @RequestMapping(value = "testParamsAndHeaders", params = { "username",
            "age!=10" }, headers = { "Accept-Language=en-US,zh;q=0.8" })
    public String testParamsAndHeaders() {
        System.out.println("testParamsAndHeaders");
        return SUCCESS;
    }

4、@RequestMapping 映射请求支持的风格:

image.png

案例:

访问地址:http://localhost:8081/mvc/testAntPath/xxxxxsa/abc

@RequestMapping(value = "testAntPath/*/abc")
    public String testAntPath()
    {
        System.out.println ("testAntPath " );
        return SUCCESS;
    }

5、@PathVariable 映射 URL 绑定的占位符
概述:

1、 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
2、 通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable("xxx") 绑定到操作方法的入参中。

访问地址:http://localhost:8081/mvc/testPathVariable/16

    @RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") Integer id) {
        System.out.println("testPathVariable: " + id);
        return SUCCESS;
    }

6、Rest风格:
案例:

    @RequestMapping(value = "testParamsAndHeaders", params = { "username",
            "age!=10" }, headers = { "Accept-Language=en-US,zh;q=0.8" })
    public String testParamsAndHeaders() {
        System.out.println("testParamsAndHeaders");
        return SUCCESS;
    }

正确访问地址:

RestTest.java

@Controller
@RequestMapping("springmvc")
public class RestTest {
    @RequestMapping(value = "testRest", method = RequestMethod.POST)
    public String hello1() {
        System.out.println ("当前是添加操作");
        return "success";
    }
    @RequestMapping(value = "testRest/{id}", method = RequestMethod.DELETE)
    public String hello2(@PathVariable Integer id) {
        System.out.println ("当前是删除操作,得到的id:"+id);
        return "success";
    }
    @RequestMapping(value = "testRest/{id}", method = RequestMethod.PUT)
    public String hello3(@PathVariable Integer id) {
        System.out.println ("当前是更新操作,得到的id:"+id);
        return "success";
    }
    @RequestMapping(value = "testRest/{id}", method = RequestMethod.GET)
    public String hello4(@PathVariable Integer id) {
        System.out.println ("当前是查询操作,得到的id:"+id);
        return "success";
    }
}

index.jsp

 <%--注: .action  是配置了后缀拦截--%>
  



查询操作

前提:在web.xml上配置Rest请求转换:

    
    
        HiddenHttpMethodFilter
        org.springframework.web.filter.HiddenHttpMethodFilter
    

    
        HiddenHttpMethodFilter
        /*
    

注意:此处可能出现jsp不支持post,请求头加上isErrorPage="true",默认为false

4、映射请求参数 & 请求头

1、概述:

方法中三注解

2、@RequestParam 绑定请求参数值

• 在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常

测试地址:http://localhost:8081/mvc/testRequestParam?username=大根

    @RequestMapping("testRequestParam")
    public String testRequestParam(@RequestParam(value = "username") String name,
                                                           @RequestParam(value = "age",required = false,defaultValue = "0") int age){
        System.out.println ("第一个参数值:"+name+",第二个无传入,默认值:"+age );
        return SUCCESS;
    }

3、@RequestHeader 绑定请求报头的属性值

请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中

测试地址:http://localhost:8081/mvc/testRequestHeader

    @RequestMapping("testRequestHeader")
    public String testRequestHeader(
            @RequestHeader("Accept-Language") String al    )
    {
        System.out.println ("请求头中Accept-Language值为:"+al );
        return SUCCESS;
    }

4、@CookieValue 绑定请求中的 Cookie 值

@CookieValue 可让处理方法入参绑定某个 Cookie 值

测试地址:http://localhost:8081/mvc/testCookieValue

    @RequestMapping("testCookieValue")
    public String testCookieValue(
            @CookieValue("JSESSIONID") String sessionId    )
    {
        System.out.println ("Cookie中Session的 ID:"+sessionId );
        return SUCCESS;
    }

5、POJO 对象绑定请求参数值

Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
如:dept.deptId、dept.address.tel 等

    测试地址:http://localhost:8081/mvc/testPojo?uid=2&uname=%E5%A4%A7%E6%A0%B9&age=11
    
    @RequestMapping("testPojo")
    public String testPojo(User user)
    {
        System.out.println ("用户的对象的属性值:"+user );
        return SUCCESS;
    }

6、Servlet API 作为入参

   测试地址:http://localhost:8081/mvc/testServletApi
    
    /**
     * HttpServletRequest
     * HttpServletResponse
     * HttpSession
     * java.security.Principal
     * Locale InputStream
     * OutputStream
     * Reader
     * Writer
     *
     * @return
     */
    @RequestMapping("testServletApi")
    public void testServletApi(HttpServletRequest req, HttpServletResponse resp, Writer out)
    throws IOException {
        System.out.println ("testServletApi:"+req+resp);
        out.write ("hello kk");
        //return SUCCESS;
    }

5、处理模型数据

概:

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

1、ModelAndView:

1.1、 控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。
1.2、 添加模型数据:
– MoelAndView addObject(String attributeName, Object attributeValue)
– ModelAndView addAllObject(Map modelMap)
1.3、 设置视图: – void setView(View view) – void setViewName(String viewName)j

    @RequestMapping("testModelAndView")
    public ModelAndView testModelAndView() {
        String viewName = SUCCESS;
        ModelAndView modelAndView = new ModelAndView (viewName);

        modelAndView.addObject ("time",new Date ());

        return modelAndView;
    }

----------------------------------------------------------------------------------------------------------------------
jsp页面:


Time: ${requestScope.time}
map: ${requestScope.names}

2、Map及Model
概:

image.png
    @RequestMapping("testMap")
    public String testMap(Map map) {
        //实际上也可以是Model类型或者ModelMap
        //org.springframework.validation.support.BindingAwareModelMap
        System.out.println (map.getClass ().getName () );
        map.put ("names", Arrays.asList ("Tom","kk","mike"));
        System.out.println (map );
        return SUCCESS;
    }

----------------------------------------------------------------------------------------------------------------------
jsp页面:


Time: ${requestScope.time}
map: ${requestScope.names}

BindingAwareModelMap继承图:

因为传入的map 实际上是BindingAwareModelMap(MVC处理的)


image.png

3、@SessionAttributes

image.png
@Controller
//value内可以指定多个;存入session域中,并且也存入request域一份
//types如果类型是String,map.put(key,value)中的value是字符串的话也会存入Session中,如果不是只会存到request
@SessionAttributes(value = {"user"},types = {String.class})//该注解只能放类上
public class RestTest {
    public static final String SUCCESS = "success";

    @RequestMapping("testSessionAtt")
    public String testSessionAtt(Map map)
    {
        User user = new User (1, "kk", 27);
        map.put ("user",user);
        map.put ("sex",1);
        map.put ("age","18");
        return SUCCESS;
    }

-----------------------------------------jsp页面-------------------------------------------------------------------------------------------
user--request:  ${requestScope.user}
user--session: ${sessionScope.user}
sex--request: ${requestScope.sex}
sex--session: ${sessionScope.sex}
//这个没有值,其他都有 age--request: ${requestScope.age}
age--session: ${sessionScope.age}

4、@ModelAttribute(重点)
1、概要:


image.png

2、案例流程:


image.png

3、@ModelAttribute详解,说明

    /**
     * 1. 有 @ModelAttribute 标记的方法, 会在每个目标方法执行之前被 SpringMVC 调用! 
     * 2. @ModelAttribute 注解也可以来修饰目标方法 POJO 类型的入参, 其 value 属性值有如下的作用:
     * 1). SpringMVC 会使用 value 属性值在 implicitModel 中查找对应的对象, 若存在则会直接传入到目标方法的入参中.
     * 2). SpringMVC 会一 value 为 key, POJO 类型的对象为 value, 存入到 request 中. 
     */



/**
     * 运行流程:
     * 1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放入到了 Map 中. 键为: user
     * 2. SpringMVC 从 Map 中取出 User 对象, 并把表单的请求参数赋给该 User 对象的对应属性.
     * 3. SpringMVC 把上述对象传入目标方法的参数. 
     * 
     * 注意: 在 @ModelAttribute 修饰的方法中, 放入到 Map 时的键需要和目标方法入参类型的第一个字母小写的字符串一致!
     * 
     * 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 中. 
     * 
     * 源代码分析的流程
     * 1. 调用 @ModelAttribute 注解修饰的方法. 实际上把 @ModelAttribute 方法中 Map 中的数据放在了 implicitModel 中.
     * 2. 解析请求处理器的目标参数, 实际上该目标参数来自于 WebDataBinder 对象的 target 属性
     * 1). 创建 WebDataBinder 对象:
     * ①. 确定 objectName 属性: 若传入的 attrName 属性值为 "", 则 objectName 为类名第一个字母小写. 
     * *注意: attrName. 若目标方法的 POJO 属性使用了 @ModelAttribute 来修饰, 则 attrName 值即为 @ModelAttribute 
     * 的 value 属性值 
     * 
     * ②. 确定 target 属性:
     *  > 在 implicitModel 中查找 attrName 对应的属性值. 若存在, ok
     *  > *若不存在: 则验证当前 Handler 是否使用了 @SessionAttributes 进行修饰, 若使用了, 则尝试从 Session 中
     * 获取 attrName 所对应的属性值. 若 session 中没有对应的属性值, 则抛出了异常. 
     *  > 若 Handler 没有使用 @SessionAttributes 进行修饰, 或 @SessionAttributes 中没有使用 value 值指定的 key
     * 和 attrName 相匹配, 则通过反射创建了 POJO 对象
     * 
     * 2). SpringMVC 把表单的请求参数赋给了 WebDataBinder 的 target 对应的属性. 
     * 3). *SpringMVC 会把 WebDataBinder 的 attrName 和 target 给到 implicitModel. 
     * 近而传到 request 域对象中. 
     * 4). 把 WebDataBinder 的 target 作为参数传递给目标方法的入参. 
     */

5、@SessionAttributes引发的异常:

讲人话,就是类上面上的@SessionAttributes( value="xxx"),xxx找不到,所有必须有,或者注释掉这个注解


image.png

解决方法:


image.png

6、视图和视图解析器

概述:

image.png
image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

案例:

@RequestMapping("show")
public String test() {
    return SUCCESS;
}

@RequestMapping("testRedirect")
public String testRedirect() {
    System.out.println ("重定向");
    return "redirect:/index.jsp";
}

你可能感兴趣的:(2-SpringMVC-1-模型和视图)