• SpringMVC 学习笔记(一) Hello World


    springMVC概述:

    Spring MVC 是目前最主流的MVC 框架之一

    Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请

    求的控制器,而无须实现任何接口。

    支持 REST 风格的 URL 请求

    采用了松散耦合可插拔组件结构,比其他 MVC 框架更具

    扩展性和灵活性

    第一步:先建立一个javaweb动态项目的工程

    工程名称为springmvc01

    2、整个项目的工程如下所示,添加所需的jar包,这里下载的spring 4.2

    3、接下来在web.xml中配置springmvc启动加载的DispatcherServlet,配置拦截客户端的所有请求,但是这里会访问不到静态资源文件后面会讲解

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        version="3.0" >
        <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
        <servlet>
            <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- 加载spirng配置文件 -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
            <!-- 启动就加载 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- 拦截所有请求 -->
        <servlet-mapping>
            <servlet-name>springDispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
        

    其中:

     <param-value>classpath:spring-mvc.xml</param-value>指定自己创建的spring-mvc的配置文件,配置文件我们放在src目录下类路径下
    第二步:创建
    spring-mvc.xml这个文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
        <!-- 配置自动扫描包  扫描com.ibigsea.springmvc 包下的类,后期会使用spring进行管理 -->
        <context:component-scan base-package="com.wst.springmvc.handlers"/>
    <!-- 配置视图解析器 如返回helloworld     
                             为 [/WEB-INF/pages/helloworld.jsp] -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <!-- 前缀 -->
            <property name="prefix" value="/WEB-INF/pages/"/>
             <!-- 后缀 -->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    这里我们要使用@control这个注解,我们配置自己扫描功能<context:component-scan base-package="com.wst.springmvc.handlers"/>,描述com.wst.springmvc.handlers这个包下面的所有control类文件
    InternalResourceViewResolver这个是配置视图解析器,解析/WEB-INF/pages/这个目录下的所有的jsp页面返回给客户端

    4、编写handler文件,这个类文件处理客户端转发过来的请求
    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HelloWrold {
    
        /***
         * 使用@RequestMapping来注册映射的请求
         * value="/helloworld"中的值必须和 <a href="helloworld">Hello world </a>一一对应
         * */
        @RequestMapping(value="/helloworld")
        public String helloworld(){
            System.out.println("helloworld is called");
            return "sucess";
        }
    }
    这里第一个类必须使用@control进行注解,表示该类是springmvc的handler处理器,第二需要使用RequestMapping对文件进行映射
    我们来看index.jsp中的href对应的helloworld就必须和@RequestMapping(value="/helloworld")一一对应起来。当业务处理完成之后,返回sucess字符串,表示的意思就是返回到/WEB-INF/pages/sucess.jsp页面
    <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
        <a href="helloworld">Hello world </a>
      </body>
    </html>

    sucess.jsp的页面内容如下
    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
         页面跳转成功
      </body>
    </html>
    我们来梳理下流程

    当用户点击index.jsp页面上的Hello world的时候,将请求转发给handler中的helloworld函数处理,处理完成后跳转到web-inf/pages/sucess.jsp页面

    3. 尚硅谷_佟刚_SpringMVC_RequestMapping_修饰类.avi

    1.我们来看@requestMapping修饰类
    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
    
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }

    其中:@RequestMapping("/springmvc")当@RequestMapping(value="/springmvc")中只有一个参数的时候,value可以省去

    这个时候在类上使用了@RequestMapping("/springmvc")修饰类,这个时候要访问handler中的testRequestMapping方法,对应的客户端的url需要改变为下面的访问形式

    http://localhost:8080/Springmvc01/springmvc/testRequestMapping

    对应的index.jsp页面修改为:

    <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
        <a href="springmvc/testRequestMapping">Hello world </a>
      </body>
    </html>

     对应的视频目录为

    4. 尚硅谷_佟刚_SpringMVC_RequestMapping_请求方式.avi

     我们编写一个函数,该函数指定客户端请求的方式必须是post的方式

    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
    
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }

    index.jsp页面修改为

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
      
       <form action="springmvc/testMethod" method="post">
        <input type="submit" value="提交"/>
       </form>
      
        <a href="springmvc/testRequestMapping">Hello world </a>
      </body>
    </html>
    5. 尚硅谷_佟刚_SpringMVC_RequestMapping_请求参数&请求头.avi
    上面我们讲了可以在requestMapping中使用method指定请求的方式,我们也可以使用params指定客户端访问的方式
    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
    
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testparams",params={"username","age!=10"})
        public String testparams(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }
    
    
    
    指定客户端访问的时候必须携带username参数和age属性,并且age属性的值不为10
    客户端访问的访问如下
       <a href="springmvc/testparams?username=35535&age=11">testparams </a>

     也客户通过Header属性指定客户端http请求的head参数
     

     6. 尚硅谷_佟刚_SpringMVC_RequestMapping_Ant 路径.avi

     7. 尚硅谷_佟刚_SpringMVC_RequestMapping_PathVariable注解.avi

    我们来看下面的一个例子

    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
    
        //指定客户端访问该testMethod函数的方式必须是post方式
            @RequestMapping(value="/testPathVariable/{id}")
            public String testPathVariable(@PathVariable Integer id){
                System.out.println("id = "+id);
                return "sucess";
            }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testparams",params={"username","age!=10"})
        public String testparams(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }
    当客户端输入:
            <a href="springmvc/testPathVariable/12">testPathVariable</a>
    我们就可以在函数testPathVariable获得客户端传递过来的值是12,关键点
    @PathVariable Integer id 指定参数的类型和名字,名字必须和

    @RequestMapping(value="/testPathVariable/{id}")中{}中的一一对应

    8.+尚硅谷_佟刚_SpringMVC_HiddenHttpMethodFilter+过滤器

    restful风格

     

     上面如果/order/1方式请求的时候,如何客户端指定的方式是get请求,表示得到id=1的数据,如何是put表示更新id=1的数据,delete表示删除id=1的数据,我们xml中只有get和post两种方式,如何实现put和delete方式了

    HiddenHttpMethodFilter进行请求过滤,实现Rest风格的url

    Rest 风格的 URL.
    以 CRUD 为例:
    新增: /order POST
    修改: /order/1 PUT update?id=1
    获取:/order/1 GET get?id=1
    删除: /order/1 DELETE delete?id=1、

    浏览器只支持Post和get的方式,想要实现delete和put的方式,需要使用过滤器HiddenHttpMethodFilter

    需要在web.xml进行配置

    2,在客户端发起请求

    过滤器使用_method的这个参数来决定过滤成是什么类型的,因此,需要在前端的提交表单里面加上_method的隐藏域,注意要使用post方法进行提交

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
      
       <form action="springmvc/testMethod" method="post">
        <input type="submit" value="提交"/>
       </form>
    
        <a href="springmvc/testRequestMapping">Hello world </a></br>
        
           <a href="springmvc/testparams?username=35535&age=11">testparams </a>
           
            <a href="springmvc/testPathVariable/12">testPathVariable</a>
            
            <form action="springmvc/rest/12" method="post">
        <input type="hidden" name="_method" value="DELETE">
        <input type="submit" value="delete">
      </form>
      <form action="springmvc/rest/12" method="post">
        <input type="hidden" name="_method" value="PUT">
        <input type="submit" value="put">
      </form>
      <form action="springmvc/rest/12" method="post">
        <input type="submit" value="post">
      </form>
      <form action="springmvc/rest/12" method="get">
        <input type="submit" value="get">
      </form>
      </body>
    </html>

    3,后端控制器的编写

    
    

    控制器直接使用RequestMapping来指定方法就可以了

    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
        
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.DELETE)
        public String testrestDELETE(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.PUT)
        public String testrestPUT(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.POST)
        public String testrestPOST(@PathVariable int id){
            return "sucess";
    
        }
    
    
        //指定客户端访问该testMethod函数的方式必须是post方式
            @RequestMapping(value="/testPathVariable/{id}")
            public String testPathVariable(@PathVariable Integer id){
                System.out.println("id = "+id);
                return "sucess";
            }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testparams",params={"username","age!=10"})
        public String testparams(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }
    总结:使用HiddenHttpMethodFilter进行请求过滤,handler使用@@PathVariable,配合使用实现Restful风格的url,在后面的增删改查中会详细的介绍

     9. 尚硅谷_佟刚_SpringMVC_RequestParam 注解.avi

    使用requestParam来获得客户端传递过来的请求的值

    在springMVC中使用RequestParam注解映射请求参数,@RequestParam有三个属性,分别如下:

    (1) value 请求参数的参数名,作为参数映射名称;

    (2) required 该参数是否必填,默认为true(必填),当设置成必填时,如果没有传入参数,报错;

    (3) defaultValue 设置请求参数的默认值;

    访问地址:

      <a href="springmvc/testRP/testRequestParam?username=35535&age=11">testparams </a>

    我们来获得对应的传递的参数username和age的值我们来看handle的代码

    package com.wst.springmvc.handlers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
        //http://localhost:9000/SpringMVC/testRP/testRequestParam?username=test&age=1
        @RequestMapping(value = "testRP/testRequestParam")
        public String testRequestParam(@RequestParam(value="username" ) String username,
                  @RequestParam(value="age",required=false) Integer age){
            System.out.println("username:"+username);
            System.out.println("age:"+age);
            return "sucess";
        }
        
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.DELETE)
        public String testrestDELETE(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.PUT)
        public String testrestPUT(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.POST)
        public String testrestPOST(@PathVariable int id){
            return "sucess";
    
        }
    
    
        //指定客户端访问该testMethod函数的方式必须是post方式
            @RequestMapping(value="/testPathVariable/{id}")
            public String testPathVariable(@PathVariable Integer id){
                System.out.println("id = "+id);
                return "sucess";
            }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testparams",params={"username","age!=10"})
        public String testparams(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }

    10. 尚硅谷_佟刚_SpringMVC_RequestHeader 注解.avi

    @RequestHeader同@RequestParam可以获得客户端中对应的http传输协议中的信息

    //@RequestHeader:获取浏览器头信息:限制请求头中必须有User-Agent
        //User-Agent:封装了浏览器的信息
        //helloMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
        @RequestMapping("show22")
        public String show22(@RequestHeader("User-Agent")String browser){
            System.out.println("hello"+browser);
            return "/index.jsp";
        }

     11. 尚硅谷_佟刚_SpringMVC_CookieValue 注解.avi

    @CookieValue的作用

      用来获取Cookie中的值

    @CookieValue参数

      1、value:参数名称

      2、required:是否必须

      3、defaultValue:默认值

    @CookieValue使用案例

    1、我们在index.jsp页面中创建cookie值

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
          <script type="text/javascript">
              document.cookie="name=caoyc;path=/"  
              document.cookie="age=18;path=/"  
              // 时间可以不要,但路径(path)必须要填写,因为JS的默认路径是当前页,如果不填,此cookie只在当前页面生效!~
          </script>
    
      </head>
      
      <body>
        <a href="testCookie">查看Cookie</a>
        
      </body>
    </html>

    2、在控制器中

    @RequestMapping("/testCookie")
    2 public String testCookie(@CookieValue(value="name",required=false) String name,
    3         @CookieValue(value="age",required=false) Integer age){
    4     System.out.println(name+","+age);
    5     return "hello";
    6 }

    测试代码

    测试1:

    我们直接访问http://localhost:8080/springmvc-1/testCookie

    输出结果为:null,null

    测试2:

    我们现在访问http://localhost:8080/springmvc-1 这里路径直接对应index.jsp页面

    进入页面后通过开发者工具,我们查看到到cookie信息

    然后再次访问http://localhost:8080/springmvc-1/testCookie

    结果输12.+尚硅谷_佟刚_SpringMVC_使用POJO作为参数

    前面我们学习了@RequestParam注解,可以获得请求的参数,但是如果前台传来的是一个表单,表单中有很多参数,那么这个时候使用@RequestParam注解一个一个去映射的话,方法中就会有N多个注解在里面,显然这种方式获取参数是不可取的。这个时候我们可以使用一个Java对象来获得请求参数。
    Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。而且支持级联属性,如:user.roleId、user.role.roleName等。

    ♦新建一个表单

       <form action="springmvc/testPojo" method="post">
            用户名: <input type="text" name="userName"/><br>
            密码: <input type="password" name="password"/><br>
            邮箱: <input type="text" name="email"/><br>
            角色: <input type="text" name="role.roleName"/><br>
            <input type="submit" value="提交"/>
        </form>

    建立两个实体类

    package com.wst.springmvc.handlers;
    public class User {
        private String userName;
        private String password;
        private String email;
        private Role role;
    
        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;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Role getRole() {
            return role;
        }
    
        public void setRole(Role role) {
            this.role = role;
        }
    
        @Override
        public String toString() {
            return "User [userName=" + userName + ", password=" + password
                    + ", email=" + email + ", role=" + role + "]";
        }
    
    }
    package com.wst.springmvc.handlers;
    public class Role {
        private String roleId;
        private String roleName;
    
        public String getRoleId() {
            return roleId;
        }
    
        public void setRoleId(String roleId) {
            this.roleId = roleId;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        @Override
        public String toString() {
            return "Role [roleId=" + roleId + ", roleName=" + roleName + "]";
        }
    
    }

    handle处理类

    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
        @RequestMapping(value = "/testPojo", method = RequestMethod.POST)
        public String testPojo(User user) {
            System.out.println("testPojo: " + user);
            return "sucess";
        }
        

    特别需要注意的是 表单中的属性value值必须和类中的一一对应

    用户名: <input type="text" name="userName"/><br>
    密码: <input type="password" name="password"/><br>
    邮箱: <input type="text" name="email"/><br>
    角色: <input type="text" name="role.roleName"/><br>
    <input type="submit" value="提交"/>

    和User类中的

    private String userName;
    private String password;
    private String email;
    private Role role;

    一一对应

     13. 尚硅谷_佟刚_SpringMVC_使用Servlet原生API作为参数.avi

    只需要在控制器的方法里添加相应的Servlet 参数即可!

    支持以下参数:

    新建一个controller类,部分代码如下:(省略xml配置文件)

    @RequestMapping("servletapi")
        public void ServletApi(HttpServletRequest request,HttpServletResponse response) throws IOException{
            String un = request.getParameter("username");
            String age = request.getParameter("age");
            PrintWriter out = response.getWriter();
            out.println(un + " " + age);
        }

    表单代码:

    运行结果:

    案例二:当客户端访问的时候使用原生的out对象返回一个字符串给客户端

    @RequestMapping(value="/testServletApi")
        public void testServletApi(HttpServletRequest request,
                HttpServletResponse response ,Writer write) throws IOException{
            //返回一个字符串给客户端
            write.write("iioioio");
            
        }

    表单访问

    如果返回中文存在乱码问题,在后面会解决

    14. 尚硅谷_佟刚_SpringMVC_处理模型数据之ModelAndView.avi

    这篇文章写怎么从后端往前端传入数据,比如从数据库查到了数据,这样传递到前端显示了

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

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

    目标方法的返回值可以是ModelAndView类型,其中可以包含视图和模型信息

          springmvc会把ModelAndView的model中数据放在request域对象中

    @RequestMapping("/springmvc")
      @Controller
      public class SpringMVCTest {
          private static final String SUCCESS = "success";
      /**
       * 目标方法的返回值可以是ModelAndView类型
       * 其中可以包含视图和模型信息
       * springmvc会把ModelAndView的model中数据放在request域对象中
       * @return*/
         @RequestMapping("/testModelAndView")
         public ModelAndView testModelAndView(){
             String viewName=SUCCESS;
             //添加模型视图
             ModelAndView modelAndView=new ModelAndView(viewName);
             //添加模型数据到ModelAndView中
             modelAndView.addObject("time", new Date());
             return modelAndView;
         }

     index.jsp

    <a href="springmvc/testModelAndView">Test ModelAndView<a>

      success.jsp

    <html>
          <h4>Success Page</h4>
         time:${requestScope.time}
     </html>

    当视图解释器解析ModelAndVIew是,其中model本生就是一个Map的实现类的子类。视图解析器将model中的每个元素都通过request.setAttribute(name, value);添加request请求域中。这样就可以在JSP页面中通过EL表达式来获取对应的值

    15 尚硅谷_佟刚_SpringMVC_处理模型数据之Map.avi

    除了使用ModelAndView方式外。还可以使用Map、Model和ModelMap来向前台页面创造

      使用后面3种方式,都是在方法参数中,指定一个该类型的参数。例如:

    @RequestMapping("/test")
    public String test(Map<String,Object> map,Model model,ModelMap modelMap){
    
        map.put("names", Arrays.asList("caoyc","zhh","cjx"));
        model.addAttribute("time", new Date());
        modelMap.addAttribute("city", "ChengDu");
        modelMap.put("gender", "male");
        return "hello";
    }

    JSP页面

    1 1、time:${requestScope.time}
    2 <br/>2、names:${requestScope.names }
    3 <br/>3、city:${requestScope.city }
    4 <br/>4、gender:${requestScope.gender }

    结果:

     16. 尚硅谷_佟刚_SpringMVC_处理模型数据之 SessionAttributes 注解.avi

    默认情况下Spring MVC将模型中的数据存储到request域中。当一个请求结束后,数据就失效了。如果要跨页面使用。那么需要使用到session。而@SessionAttributes注解就可以使得模型中的数据存储一份到session域中。

     1、names:这是一个字符串数组。里面应写需要存储到session中数据的名称。

      2、types:根据指定参数的类型,将模型中对应类型的参数存储到session中

        3、value:其实和n

    1 @RequestMapping("/test")
    2 public String test(Map<String,Object> map){
    3     map.put("names", Arrays.asList("caoyc","zhh","cjx"));
    4     map.put("age", 18);
    5     return "hello";
    6 }

    Jsp页面

    1 1、request中names:${requestScope.names}<br/>
    2 2、request中age:${requestScope.age}<br/>
    3 <hr/>
    4 3、session中names:${sessionScope.names }<br/>
    5 4、session中age:${sessionScope.age }<br/>

    显示结果:

    【总结】:上面代码没有指定@SessionAttributes,所有在session域总无法获取到对应的数据。

    下面我们加上@SessionAttributes注解

    @SessionAttributes(value={"names"},types={Integer.class})
    @Controller
    public class Test {
    
        @RequestMapping("/test")
        public String test(Map<String,Object> map){
            map.put("names", Arrays.asList("caoyc","zhh","cjx"));
            map.put("age", 18);
            return "hello";
        }
    }

    再次访问页面:

    可以看到session域中值已存在

    【注意】:@SessionAttributes注解只能在类上使用,不能在方法上使用

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

    @SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中。

    1. @SessionAttributes(types=User.class)会将隐含模型中所有类型为 User 的属性添加到会话中

    2. @SessionAttributes(value={"user1", "user2"})将名为 user1 和 user2 的模型属性添加到会话中

    3. @SessionAttributes(types={"User.class", "Dept.class"})将模型中所有类型为 User 及 Dept 的属性添加到会话中

    4. @SessionAtributes(value={"user1", "user2"}, types={Dept.class})将名为 user1 和 user2 的模型属性添加到会话中,同时将所有类型为 Dept 的模型属性添加到会话中

    17. 尚硅谷_佟刚_SpringMVC_ModelAttribute注解之使用场景.avi

    @ModelAttribute放置的位置不同也有不同的功能。那么@ModelAttribute可以放置在哪些位置呢?如下:
    可以在方法入参上使用@ModelAttribute注解
    还可以在方法定义中使用@ModelAttribute注解

    @ModelAttribute("user")
    public User getUser(){          <---1//访问UserController中的任何一个请求处理方法前,
        User user = new User();         //SpringMVC先执行该方法,并将返回值以user为键添加到模型中 
        user.setUserId("1001");
        return user;
    }
    @RequestMapping(value="/model")
    public String handleModel(@ModelAttribute("user") User user){     <---2 //在此,模型数据会赋给User的入参,
        user.setUserName("tom");                                           //然后再根据HTTP请求消息进一步填充覆盖user对象
        return "/user/showUser";
    }
    当访问UserController中的任何一个请求处理方法前,都会事先执行标注了@ModelAttribute的getUser()方法,并将其返回值以user为键添加到模型中。
    由于 ② 处的handleModel()方法使用了入参级的@ModelAttribute注解,且属性名和 ① 处方法级@ModelAttribute的属性名相同。这时,SpringMVC会将 ① 处获取的模型属性先赋值给 ② 处的人参user,然后再根据HTTP请求消息对user进行填充覆盖,得到一个整合版本的user对象。
    这句话啥意思了:
    我们来看下面的一个例子
    现在数据库中存在一个id=1的用户数据,我们使用modelAttitue实现下面的功能,首先依据id从数据库中查询出该用户的所有数据,然后通过页面修改该用户的其他属性值,但是该用户的密码不能被修改,然后将修改后的数据保存到数据库中,如何实现了
    我们先建立一个User的实体类
    package com.wst.springmvc.handlers;
    public class User {
        private Integer id ;
        private String userName;
        private String password;
        private String email;
        private Role role;
    
        
        
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer 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;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Role getRole() {
            return role;
        }
    
        public void setRole(Role role) {
            this.role = role;
        }
    
        @Override
        public String toString() {
            return "User [userName=" + userName + ", password=" + password
                    + ", email=" + email + ", role=" + role + "]";
        }
    
    }

     第二步建立一个修改页面,该修改页面提交需要修改的数据

       <form action="springmvc/testModelAttribute" method="post">
           <input  type="hidden" name="id" value="1"/>
            用户名: <input type="text" name="userName"/><br>
            邮箱: <input type="text" name="email"/><br>
            <input type="submit" value="提交修改"/>
        </form>
    第三步handle处理器
    @ModelAttribute
        public void  getUsrById(@RequestParam(value="id",required = false) String id,Map<String, Object> map){
            int user_id = Integer.parseInt(id);
            //模拟依据id从数据库中得到该用户的所有信息
            User user = new User();    
            user.setId(Integer.parseInt(id));
            user.setUserName("Tom");
            user.setPassword("123456");
            user.setEmail("555@qq.com");
            //将user对象存储在map域中
            map.put("user", user);
            }
        
        @RequestMapping(value="/testModelAttribute",method=RequestMethod.POST)
         public String  testModelAttribute(User user){
             System.out.println("user is :"+ user.toString());
             return "sucess";
             
         }

     我们来说下业务流程

     当用户提交修改提交的时候,使用@ModelAttribute修饰的方式会在调用的 testModelAttribute之前被调用,当访问Controller中的任何一个请求处理方法前,都会事先执行标注了@ModelAttribute的方法,在改方法中我们首先获得jsp修改页面传递过来的id值,我们模拟通过id从数据库中查询出对应的user_A,我们把该对象保存到map集合中,并且保存到了request作用域中

    第二步:然后访问testModelAttribute对象的时候,通过requestMapping封装java对象可以知道,testModelAttribute(User user)中的参数User user可以获得从jsp页面传递过的参数值,这个时候会干啥事情了,会将修改对象提交的用户名和密码

    去修改保存在作用域中user_A对象中的用户名和邮箱的值,密码没有被修改还是原来得密码,提交只是修改了user_A对象中的用户名和密码, 其他参数属性值没有被修改

    我们来看下打印

    user is :User [id=1, userName=天才, password=123456, email=789@qq.com, role=null]

    这里有一点必须要注意的上面这种方式中  map.put("user", user);中key的值必须和 testModelAttribute(User user)形参一样,并且都必须是类名的第一个字母小写

     如果上面不一样,我们在map中存放的值是map.put("abc", user);在入参形参中可以使用下面的参数进行解决

    下面的方法默认等价于
         public String  testModelAttribute(User user){
             System.out.println("user is :"+ user.toString());
             return "sucess";
             
         }
    public String  testModelAttribute(@ModelAttribute("user") User user){
             System.out.println("user is :"+ user.toString());
             return "sucess";
             
         }

     默认是类名的第一个小写字母

    @Controller
    @RequestMapping("/springmvc")
    public class SpringMvcTest {
        
        @ModelAttribute
        public void  getUsrById(@RequestParam(value="id",required = false) String id,Map<String, Object> map){
            int user_id = Integer.parseInt(id);
            //模拟依据id从数据库中得到该用户的所有信息
            User user = new User();    
            user.setId(Integer.parseInt(id));
            user.setUserName("Tom");
            user.setPassword("123456");
            user.setEmail("555@qq.com");
            //将user对象存储在map域中
            map.put("abc", user);
            }
        
        @RequestMapping(value="/testModelAttribute",method=RequestMethod.POST)
         public String  testModelAttribute(@ModelAttribute("abc") User user){
             System.out.println("user is :"+ user.toString());
             return "sucess";
             
         }

     23. 尚硅谷_佟刚_SpringMVC_SessionAttributes注解引发的异常.avi

    使用@ModelAttribute和@SessionAttributes配合使用的时候可能会产生下面的异常

    先说明下业务的操作流程:使用@ModelAttribute("abc")首先会从map中查询key为abc的对象是否存在,如果存在直接使用,如果map对象中不存在,只看类是否使用了@SessionAttributes(value="abc")修饰

    如果修饰了,但是session中不存在key=abc对象的对象,会抛出异常

     

    Spring MVC封装一个pojo的原理如下所示:

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

    1、确认一个key:

      (1)、若目标方法的POJO类型的参数没有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写

      (2)、若使用@ModelAttribute来修饰,则key为@ModelAttibute注解的value属性值。

    1 @RequestMapping("/updateUser")
    2 public String update(User user){

      这里没有使用@ModelAttribute修饰,所有对应的key为POJO类名首字母小写,即为:user

    1 public String update(@ModelAttribute("abc") User user)

      这里使用了@ModelAttribute来修饰POJO,那么对应的可以为@ModelAttribute的value而值,即为:abc

      

    2、在implicitModel中查找key对应的对象。若存在,则作为参数传入

      (1)、若在@ModelAttibute标记的方法中在Map中保存过POJO,且key和1中确认的key一致,则会获取。例如:

    复制代码
     1 package com.proc;
     2 
     3 import java.util.Map;
     4 
     5 import org.springframework.stereotype.Controller;
     6 import org.springframework.web.bind.annotation.ModelAttribute;
     7 import org.springframework.web.bind.annotation.RequestMapping;
     8 import org.springframework.web.bind.annotation.RequestParam;
     9 
    10 @Controller
    11 public class UserController {
    12 
    13     
    14     @ModelAttribute
    15     public void getUser(@RequestParam(required=false) Integer id,Map map){
    16         if(id!=null){
    17             User user=new User();
    18             user.setId(1);
    19             user.setUsername("caoyc");
    20             user.setAge(18);
    21             user.setPassword("123456");
    22             map.put("user", user);
    23         }
    24     }
    25     
    26     @RequestMapping("/updateUser")
    27     public String update(@ModelAttribute("abc") User user){
    28         System.out.println("更新User对象为:"+user);
    29         return "success";
    30     }
    31 }
    复制代码

      JSP页面

    复制代码
     1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
     2 
     3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     4 <html>
     5   <head>
     6 
     7   </head>
     8   
     9   <body>
    10     <form action="updateUser" method="post">
    11         <input type="hidden" name="id" value="1">
    12         <table>
    13             <tr>
    14                 <td>用户名:</td><td><input type="text" name="username" value="caoyc"/></td>
    15             </tr>
    16             <tr>
    17                 <td>年龄:</td><td><input type="text" name="age" value="12"/></td>
    18             </tr>
    19             <tr>
    20                 <td></td><td><input type="submit" value="提交"></td>
    21             </tr>
    22            </table>
    23     </form>
    24   </body>
    25 </html>
    复制代码

      结果在控制台中输出:User [id=1, username=caoyc, password=123456, age=12]

        其中原因是:在方法/updateUser时对应的方法update( User user)时,先要执行@ModelAttribute标记的方法,而在@ModelAttribute中向implicitModel中保存了一个key为user的POJO对象。而此时update对象中参数的key为POJO类名首字母小写,也是user,也就是在implicitModel中存在该key和对应的POJO对象。那么就会以该对象作为原始值。而JSP页面中传入过来的POJO对象属性不为空且有变化的属性来修改原始值。

      原始对象:User [id=1, username=caoyc, password=123456, age=18]

      JSP中 :User[id=1, username=caoyc, password=null, age=12]

      这里需要修改的属性为age。在原始值得基础上修改了将age修改为12

      所以最总在implicitModel中key值为user的POJO对象为:User [id=1, username=caoyc, password=123456, age=12]

      

    3、座implicitModel中不存在key对应的对象,则检查当前的Handler是否使用了@SessionAttributes注解修饰,若使用了该注解,且@SessionAttribute注解的value属性值中包含了key,则会从HttpSession中获取key所对应的value值,若存在则直接传入到目标方法的入参中,若不存在则将抛出异常。

       Java代码

    复制代码
     1 @SessionAttributes(value={"user"})
     2 @Controller
     3 public class UserController {
     4 
     5     @RequestMapping("/updateUser")
     6     public String update(User user){
     7         //System.out.println("更新User对象为:"+user);
     8         return "success";
     9     }
    10 }
    复制代码

      此时,如果session中没有key为user的值,那么只需/updateUser时会抛出异常。因为在只需目标方法时,发现类有@SessionAttributes注解,且目标方法需要一个key为user的POJO对象,该key还存在@SessionAttributes注解的value中,所以会抛出异常。如果此时session中存在key为user的值,则将该值传入目标方法参数。

      怎么解决异常?

      方法一:添加一个使用@ModelAttribute的注解的方法,该方法向implicitModel保存一个为key为user的POJO

      方法二:去掉@SessionAttributes注解

      方法三:修改目标参数的key值。例如 @ModelAttribute(value="user2") User user

      

     

    4、若Handler没有标识@SessionAttributes注解或@SessionAttributes注解的value值中不包含key,则会通过反射来创建POJO类型的参数,并作为参数传入到目标方法

    5、SpringMVC会把key和POJO类型的对象保存到imlicitModel中,进而会保存到request中。

    我们来看下代码

    package com.wst.springmvc.handlers;
    
    import java.io.IOException;
    import java.io.Writer;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.CookieValue;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.SessionAttributes;
    
    @Controller
    @RequestMapping("/springmvc")
    @SessionAttributes(value="abc")
    public class SpringMvcTest {
        
        /*@ModelAttribute
        public void  getUsrById(@RequestParam(value="id",required = false) String id,Map<String, Object> map){
            int user_id = Integer.parseInt(id);
            //模拟依据id从数据库中得到该用户的所有信息
            User user = new User();    
            user.setId(Integer.parseInt(id));
            user.setUserName("Tom");
            user.setPassword("123456");
            user.setEmail("555@qq.com");
            //将user对象存储在map域中
            map.put("abc", user);
            }*/
        
        @RequestMapping(value="/testModelAttribute",method=RequestMethod.POST)
         public String  testModelAttribute(@ModelAttribute("abc") User user){
             System.out.println("user is :"+ user.toString());
             return "sucess";
             
         }
            
        
        
        @RequestMapping(value="/testServletApi")
        public void testServletApi(HttpServletRequest request,
                HttpServletResponse response ,Writer write) throws IOException{
            //返回一个字符串给客户端
            write.write("iioioio");
            
        }
        @RequestMapping(value = "/testPojo", method = RequestMethod.POST)
        public String testPojo(User user) {
            System.out.println("testPojo: " + user);
            return "sucess";
        }
        
        //http://localhost:9000/SpringMVC/testRP/testRequestParam?username=test&age=1
        @RequestMapping(value = "testRP/testRequestParam")
        public String testRequestParam(@CookieValue(value="username" ) String username,
                  @RequestParam(value="age",required=false) Integer age){
            System.out.println("username:"+username);
            System.out.println("age:"+age);
            return "sucess";
        }
        
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.DELETE)
        public String testrestDELETE(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.PUT)
        public String testrestPUT(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.POST)
        public String testrestPOST(@PathVariable int id){
            return "sucess";
    
        }
    
    
        //指定客户端访问该testMethod函数的方式必须是post方式
            @RequestMapping(value="/testPathVariable/{id}")
            public String testPathVariable(@PathVariable Integer id){
                System.out.println("id = "+id);
                return "sucess";
            }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testparams",params={"username","age!=10"})
        public String testparams(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }
    上面代码屏蔽了getUsrById方法,运行的时候就会抛出下面的异常
    org.springframework.web.HttpSessionRequiredException: Session attribute 'abc' required - not found in session
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseSessionRequiredException(AnnotationMethodHandlerAdapter.java:789)
        org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:772)
        org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:369)
        org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:173)
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:444)
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:432)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:871)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
        org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    
    
    
    第二种异常:
    package com.wst.springmvc.handlers;
    
    import java.io.IOException;
    import java.io.Writer;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.CookieValue;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.SessionAttributes;
    
    @Controller
    @RequestMapping("/springmvc")
    @SessionAttributes(value="user")
    public class SpringMvcTest {
        
        /*@ModelAttribute
        public void  getUsrById(@RequestParam(value="id",required = false) String id,Map<String, Object> map){
            int user_id = Integer.parseInt(id);
            //模拟依据id从数据库中得到该用户的所有信息
            User user = new User();    
            user.setId(Integer.parseInt(id));
            user.setUserName("Tom");
            user.setPassword("123456");
            user.setEmail("555@qq.com");
            //将user对象存储在map域中
            map.put("abc", user);
            }*/
        
        @RequestMapping(value="/testModelAttribute",method=RequestMethod.POST)
         public String  testModelAttribute( User user){
             System.out.println("user is :"+ user.toString());
             return "sucess";
             
         }
            
        
        
        @RequestMapping(value="/testServletApi")
        public void testServletApi(HttpServletRequest request,
                HttpServletResponse response ,Writer write) throws IOException{
            //返回一个字符串给客户端
            write.write("iioioio");
            
        }
        @RequestMapping(value = "/testPojo", method = RequestMethod.POST)
        public String testPojo(User user) {
            System.out.println("testPojo: " + user);
            return "sucess";
        }
        
        //http://localhost:9000/SpringMVC/testRP/testRequestParam?username=test&age=1
        @RequestMapping(value = "testRP/testRequestParam")
        public String testRequestParam(@CookieValue(value="username" ) String username,
                  @RequestParam(value="age",required=false) Integer age){
            System.out.println("username:"+username);
            System.out.println("age:"+age);
            return "sucess";
        }
        
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.DELETE)
        public String testrestDELETE(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.PUT)
        public String testrestPUT(@PathVariable int id){
            return "sucess";
        }
        @RequestMapping(value = "/rest/{id}",method = RequestMethod.POST)
        public String testrestPOST(@PathVariable int id){
            return "sucess";
    
        }
    
    
        //指定客户端访问该testMethod函数的方式必须是post方式
            @RequestMapping(value="/testPathVariable/{id}")
            public String testPathVariable(@PathVariable Integer id){
                System.out.println("id = "+id);
                return "sucess";
            }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testMethod",method=RequestMethod.POST)
        public String testMethod(){
            return "sucess";
        }
        
        //指定客户端访问该testMethod函数的方式必须是post方式
        @RequestMapping(value="/testparams",params={"username","age!=10"})
        public String testparams(){
            return "sucess";
        }
        
        @RequestMapping("/testRequestMapping")
        public String testRequestMapping(){
            return "sucess";
        }
    }
    
    
    
     也会抛出同上面一样的异常,因为 public String  testModelAttribute( User user)默认等价于 public String  testModelAttribute(@ModelAttribute("user") User user),其中key为对象的第一个字母的小写
    这里千万一定要注意

     24. 尚硅谷_佟刚_SpringMVC_视图解析流程分析.avi

    本篇主要讲述SpringMVC如何解析、渲染视图并转发返回结果对象。

    请求处理方法执行完成后,最终返回一个ModelAndView对象。对于那些返回String,view或者ModelMap等类型的处理方法,SpringMVC也会在内部将他们装配成一个ModelAndView对象。

    它包含了逻辑名和模型对象,其中的model可能为 { }空。

    首先说明springmvc.xml中视图解析器配置注意事项:

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>

    说明一下,如果前缀为 /WEB-INF/views/,那么后台return视图名”/success” or “success”均映射到 /WEB-INF/views/success.jsp ;

    如果前缀 为 /WEB-INF/views,那么后台return视图名”/success”,将会映射到/WEB-INF/views/success.jsp;如果后台return视图名”success”,将会报错!

     对于控制器的目标方法,无论其返回值是String、View、ModelMap或是ModelAndView,SpringMVC都会在内部将它们封装为一个ModelAndView对象进行返回。 
       Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是JSP也可是Excell、 
    JFreeChart等各种表现形式的视图。

    SpringMVC的视图解析流程

      SpringMVC的视图解析流程为: 
       
    1、调用目标方法,SpringMVC将目标方法返回的String、View、ModelMap或是ModelAndView都转换为一个ModelAndView对象;

    2、然后通过视图解析器(ViewResolver)对ModelAndView对象中的View对象进行解析,将该逻辑视图View对象解析为一个物理视图View对象;

    3、最后调用物理视图View对象的render()方法进行视图渲染,得到响应结果。

    25. 尚硅谷_佟刚_SpringMVC_JstlView.avi

    若项目中使用了jstl标签,视图解析器会将视图解析成JstlView视图

    接下来我们是jstl实现一个国际化功能

    为什么要配置国际化资源文件

    当我们所做的网站,有可能被外国人访问,或者被浏览器语言为英语的用户访问时,我们就需要配置国际化资源文件。配置之后,可以根据浏览器的语言(中文或英文),自动显示对应的语言。
    先来看看配置后的效果:
    这里我们使用IE浏览器,一般情况下的显示界面如下
    这里写图片描述
    然后点击工具->Internet选项->语言
    这里写图片描述
    点击添加,加入英语(美国)[en-US],点击上移,将其移动到第一行(截图中还未上移),点击确定
    刷新页面,发现中文变成了英文
    这里写图片描述

    如何配置国际化资源文件

    1.在src目录下创建三个properties文件

    1.在src目录下创建三个properties文件 
    这里写图片描述 
    截图中第一个文件和第三个文件内容一致 
    这里写图片描述 
    第二个文件中,则使用中文 
    这里写图片描述 
    (当你输入中文时,会被自动编码成如图所示的内容)

    接下来在spring-mvc中配置下面的内容

    <!-- 配置国际化资源文件 -->
    <bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="i18n"></property>
    </bean>

    spring-mvc.xml内容如下

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
        <!-- 配置自动扫描包  扫描com.ibigsea.springmvc 包下的类,后期会使用spring进行管理 -->
        <context:component-scan base-package="com.wst.springmvc.handlers"/>
    <!-- 配置视图解析器 如返回helloworld     
                             为 [/WEB-INF/pages/helloworld.jsp] -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <!-- 前缀 -->
            <property name="prefix" value="/WEB-INF/pages/"/>
             <!-- 后缀 -->
            <property name="suffix" value=".jsp"/>
        </bean>
        
            <!-- 配置国际化资源文件 -->
        <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
                <property name="basename" value="i18n"></property>  
        </bean>
    </beans>

    接下来在需要使用显示用户名和密码的jsp页面添加fmt国际化解析的标签,同时需要添加对应的jstl jar包我们是在sucess.jsp页面中

    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

    3.你想要国际化的内容处使用fmt标签

    <fmt:message key="i18n.username"></fmt:message>
        <br><br>
    
        <fmt:message key="i18n.password"></fmt:message>
        <br><br>

    sucess.jsp页面的内容如下所示

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
         页面跳转成功
         <fmt:message key="i18n.username"></fmt:message>
        <br><br>
    
        <fmt:message key="i18n.password"></fmt:message>
        <br><br>
      </body>
    </html>

    26. 尚硅谷_佟刚_SpringMVC_mvc_view-controller标签.avi

     对应WEB-INF目录下面的JSP页面,我们知道是不能直接使用URL访问到。需要通过转发的方式,而我们一般都是在控制器中做转发映射,对应一些我们不需要其他操作的JSP页面,我们可以使用<mvc:view-controller path=""/>来配置,这样就可以不用再控制器中再去做转发映射

    看在spring-mvc配置文件中配置

    <mvc:view-controller path="/abc" view-name="sucess"/>
        <mvc:annotation-driven></mvc:annotation-driven>

    其中path对应的是url的访问路径,

    view-name对应的是你要访问的jsp页面的名字

    我们来看看整个配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
        <!-- 配置自动扫描包  扫描com.ibigsea.springmvc 包下的类,后期会使用spring进行管理 -->
        <context:component-scan base-package="com.wst.springmvc.handlers"/>
    <!-- 配置视图解析器 如返回helloworld     
                             为 [/WEB-INF/pages/helloworld.jsp] -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <!-- 前缀 -->
            <property name="prefix" value="/WEB-INF/pages/"/>
             <!-- 后缀 -->
            <property name="suffix" value=".jsp"/>
        </bean>
        
            <!-- 配置国际化资源文件 -->
        <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
                <property name="basename" value="i18n"></property>  
        </bean>
        
        <mvc:view-controller path="/abc" view-name="sucess"/>
        <mvc:annotation-driven></mvc:annotation-driven>
    </beans>

    在浏览器中输入http://localhost:8080/Springmvc01/abc,访问的就是/WEB-INF/pages/sucess.jsp页面,不经过handler进行处理

    整个项目的工程代码如下所示

  • 相关阅读:
    单例设计模式
    程序员眼中的中国传统文化王阳明《传习录》10
    程序员眼中的中国传统文化王阳明《传习录》8
    程序员眼中的中国传统文化王阳明《传习录》16
    程序员眼中的中国传统文化王阳明《传习录》11
    程序员眼中的中国传统文化王阳明《传习录》15
    程序员眼中的中国传统文化王阳明《传习录》14
    程序员眼中的中国传统文化王阳明《传习录》9
    程序员眼中的中国传统文化王阳明《传习录》13
    程序员眼中的中国传统文化王阳明《传习录》12
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/8832164.html
Copyright © 2020-2023  润新知