springMVC框架学习安排

第一天

1. MVC基本概念


由图可见MVC架构和我们之前所学的spring和MyBatis可以完美衔接,也是web应用开发必不可少的一部分,springMVC是一个MVC设计模型的一个框架。
三层框架的执行流程:
controller接受浏览器的请求,调用model可以将其封装成JavaBean对象,发送给业务层处理,业务层又可以调用持久层与数据库交互,将返回结果发送给表现层,封装成JSP或者其它的视图,响应给浏览器。

1.springMVC的基本概述

1.什么是springMVC
springMVC 是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,
属于Spring FrameWork的后续产品,已经融合在Spring Web Flow里面。
Spring框架提供了构建Web应用程序的全功能MVC模块。使用Spring 可插入的MVC
架构,从而在使用Spring 进行WEB开发时,可以选择使用Spring的Spring MVC 
框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。

springMVC 已经成为了主流的MVC框架之一,并且随着spring3.0的发布,
全面超越了struts2,成为了最优秀的MVC框架。
它通过一套注解,让一个简单的Java类成为处理请求的控制器,
并且无需实现任何接口,同时它还支持RESTful编程风格。
2. springMVC的优势
  1. 清晰的角色划分:
    前端控制器(DispatcherServlet)
    请求到处理器映射(HandlerMapping)
    处理器适配器(HandlerAdapter)
    视图解析器(ViewResolver)
    处理器或页面控制器(Controller)
    验证器( Validator)
    命令对象(Command 请求参数绑定到的对象就叫命令对象)
    表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
  2. 分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
  3. 由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
  4. 和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
  5. 可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
  6. 可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。
  7. 功能强大的数据验证、格式化、绑定机制。
  8. 利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。
  9. 本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
  10. 强大的 JSP 标签库,使 JSP 编写更容易。
    ………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配
    置支持等等。
3. springMVC和struts2的区别(面试问题)
共同点:
	它们都是表现层框架,都是基于 MVC 模型编写的。
	它们的底层都离不开原始 ServletAPI。
	它们处理请求的机制都是一个核心控制器。
区别:
	Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
	Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所
	以 Spring MVC 会稍微比 Struts2 快些。
	Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便
	(JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注
	解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验了。)
	Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提
	升,尤其是 struts2 的表单标签,远没有 html 执行效率高。

2. springMVC的入门

  1. 入门案例需求分析

  2. 编写代码

    1. 创建maven工程,选择webapp项目
    2. pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.liuzeyu</groupId>
      <artifactId>day03_springMVC01_start</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>day03_springMVC01_start Maven Webapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!--spring版本绑定-->
        <spring.version>5.0.2.RELEASE</spring.version>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>${spring.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring.version}</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.0</version>
          <scope>provided</scope>
        </dependency>
    
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <finalName>day03_springMVC01_start</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
          <plugins>
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
            <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-war-plugin</artifactId>
              <version>3.2.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>
    
    
    1. controller控制器处理

      添加Java和resource文件完善maven项目的目录结构
      @RequestMapping注解的作用是用于建立请求URL处理请求方法之间的对应关系。
    2. spring配置文件
    <?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:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--配置创建springIOC容器时要扫描的包-->
        <context:component-scan base-package="com.liuzeyu"></context:component-scan>
    
        <!--配置视图解析器-->
        <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    
        <!--配置spring开启注解mvc的支持-->
        <mvc:annotation-driven></mvc:annotation-driven>
    
    </beans>
    
    1. 配置servlet
    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
    
      <!--配置servlet-->
      <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
        <!--servlet启动后需要加载的spring配置文件-->
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    
    1. index.jsp与success.jsp
    <%@page contentType="text/html; charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>springmvc入门</title>
    </head>
    <body>
    
    <h3>入门程序</h3>
    <a href="hello">请求</a>
    </body>
    </html>
    
    <%@page contentType="text/html; charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>入门成功</title>
    </head>
    <body>
    
    <h2>springmvc入门成功</h2>
    </body>
    </html>
    
    1. springMVC执行流程

      注意:@RequestMapping的path属性和方法执行的return 可以不以 / 开头,内部已经对其进行配置。
      springMVC内部执行的详细信息

    服务器一经启动,DisPatcherServlet对象(前端控制器)被创建,springMVC.xml被加载,HelloMVC对象也被创建。
    当我们点击a标签后,带有uri = /hello的请求被发到了前端控制器,它会带引这个请求去寻找处理器映射器,找到要执行的方法sayHello并返回(等下才要执行),当然前端控制器是不会执行这个方法,它会再次将这个结果发送到处理器适配器。
    处理器适配器会适配controller下任何的方法,处理器适配器又会发送到处理器这个组件进行方法的执行与返回,执行后返回ModelAndView给处理器适配器,处理器适配器又会将其返回到前端控制器,前端控制器将这个结果发送到视图解析器ViewResolver。
    视图解析器解析完之后又会将结果返回View前端控制器,前端控制器将View发送给View视图组件解析,视图将其解析成浏览器可以识别的出来的文件进行展示。

1. 涉及到组件

1. DispatcherServlet:前端控制器

用户的请求到达前端控制器器后,DispatcherServlet对象它就相当于mvc模式执行流程的控制中心,它调用其它组件处理用户的请求,前端控制器的存在降低了组件之间的耦合性。

2. HandlerMapping:处理器映射器

HandlerMapping负责根据用户请求找到Handler,即处理器,springMVC提供了不同的映射器实现不同的映射方式。例如配置文件方式,实现接口方式,注解方式等。

3. Handler:处理器

处理器是我们开发中要编写的具体业务控制器,由前端控制器把用户请求发送到处理器,由处理器将用户的请求进行业务处理。

4. HandlAdapter:处理器适配器

通过处理器适配器对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行

上图是电脑外接显示器的适配器,可以实现电脑连接不同的显示屏。

5. View Resolver:视图解析器

View Resolver解析器将处理结果生成视图View,View Resolver首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成view视图对象,最后对view进行渲染将处理结果以页面展示给前端

6. View视图器

作用就是将页面标签或模型数据通过页面展示给前端,SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是 jsp。

2.< mvc:annotation-driven>说明

在springMVC的各个组件中,处理器映射器,处理器适配器,视图解析器被称为springMVC的三大组件。
当在spring的配置文件中添加

    <!--配置spring开启注解mvc的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>

即默认开启使 用RequestMappingHandlerMapping (处理映射器) 和
RequestMappingHandlerAdapter ( 处 理 适 配 器 )。

3.RequestMapping注解

查看源码:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}

作用:用于建立请求 URL 和处理请求方法之间的对应关系。
作用的位置:方法上,类上。

  1. path或value属性拥有相同的作用
    通常在实际开发中我们是类上和方法上配合使用,将xxx类模块话,方法是细分的小模块,赋值为path或value属性
    如:
    • 账户模块:
      /account/add
      /account/update
      /account/delete
    • 订单模块:
      /order/add
      /order/update
      /order/delete
      红色的部分就是把 RequsetMappding 写在类上,使我们的 URL 更加精细。
      方法上:
      请求 URL 的第二级访问目录。

示例:

@Controller
@RequestMapping("/user")
public class HelloMVC {
   

    @RequestMapping(path = "hello")
    public String sayHello(){
   
        System.out.println("helloMVC........");
        return "success";
    }

    @RequestMapping(path = "/good")
    public String sayGood(){
   
        System.out.println("goodMVC........");
        return "success";
    }
}

请求的url

<a href="user/hello">请求hello</a>
<a href="user/good">请求good</a>

经测试,在 @RequestMapping不管作用在哪里,它的path路径,都可以不用写 / ,但是又时候为了阅读方便会写上。

  1. method:用于指定请求的方式
// 这样配置后通过a标签发送的get请求的将不能执行到该方法
    @RequestMapping(path = "hello",method = {
   RequestMethod.POST})
    public String sayHello(){
   
        System.out.println("helloMVC........");
        return "success";
    }
  1. params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。
    @RequestMapping(path = "/good",params = {
   "username=liuzeyu"})
    public String sayGood(){
   
        System.out.println("goodMVC........");
        return "success";
    }
<a href="user/good?username=liuzeyu">请求good</a>

a标签必须配置相应的key value的请求参数和请求值,方法才可以被执行。

  1. header:用于指定限制请求消息头的条件,浏览器消息头的请求参数必须和配置一样方法才可以被执行。

问题:为什么注解属性只传一个时,属性名可以不写

- 如果注解只有一个属性,那么肯定是赋值给该属性。
- 如果注解有多个属性,而且前提是这多个属性都有默认值,那么你不写注解名赋值,会赋值给名字为“value”这属性。
- 如果注解有多个属性,其中有没有设置默认值的属性,那么当你不写属性名答进行赋值的时候,是会报错的。

3. 请求参数的绑定

1. 请求参数绑定入门

  1. 新建控制器
@Controller
@RequestMapping("/params")
public class ParamsMVC {
   

    /** * 请求参数绑定入门 * @return */
    @RequestMapping("basic")
    public String basic(String username,String password){
   
        System.out.println("basic..."+username+"---" +password);
        return "success";
    }
}
  1. 请求链接
<a href="params/basic?username=liuzeyu&password=123">请求参数绑定入门</a>

注意:请求参数一定要和方法的参数一致。

  1. 访问127.0.0.1:8080/params/basic测试输出

2. 请求参数绑定实体类型

  1. 准备实体类
public class Account {
   

    private Integer id;
    private String name;
    private Double money;

    private User user;


    public Integer getId() {
   
        return id;
    }

    public void setId(Integer id) {
   
        this.id = id;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public Double getMoney() {
   
        return money;
    }

    public void setMoney(Double money) {
   
        this.money = money;
    }

    public User getUser() {
   
        return user;
    }

    public void setUser(User user) {
   
        this.user = user;
    }

    @Override
    public String toString() {
   
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}

public class User {
   
    private String uname;
    private Integer age;

    public String getUname() {
   
        return uname;
    }

    public void setUname(String uname) {
   
        this.uname = uname;
    }

    public Integer getAge() {
   
        return age;
    }

    public void setAge(Integer age) {
   
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "User{" +
                "uname='" + uname + '\'' +
                ", age=" + age +
                '}';
    }
}

  1. 编写controller
@Controller
@RequestMapping("/params")
public class ParamsMVC {
   

    /** * 请求参数绑定实体类 * @return */
    @RequestMapping("domain")
    public String domain(Account account){
   
        System.out.println(account);
        return "success";
    }
}
  1. jsp请求页面
<form action="/params/domain" method="post">
    账户id:<input type="text" name="id"><br>
    账户公司:<input type="text" name="name"><br>
    账户金额:<input type="text" name="money"><br>
    用户名:<input type="text" name="user.uname"><br>
    年龄:<input type="text" name="user.age"><br>
    <input type="submit" value="提交">
</form>
  1. 测试发现post方式存在参数值的中文问题

3. 请求参数中文问题

上述的中文问题可以通过配置拦截器来解决编码问题,在web.xml中配置

 <!--处理post请求的中文乱码问题-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern> </filter-mapping> 

就可以解决post请求的中文问题。

4. 请求参数为集合类型

  1. 为Account添加集合属性,并生成getXXX和setXXX方法
    private List<User> list;
    private Map<String,User> map;
  1. jsp文件
<form action="/params/domain" method="post">
    账户id:<input type="text" name="id"><br>
    账户公司:<input type="text" name="name"><br>
    账户金额:<input type="text" name="money"><br>
    用户名:<input type="text" name="list[0].uname"><br>
    年龄:<input type="text" name="list[0].age"><br>
    <br>
    用户名:<input type="text" name="map['one'].uname"><br>
    年龄:<input type="text" name="map['one'].age"><br>
    <input type="submit" value="提交">
</form>

重点注意name属性的写法。

  1. 测试
    @RequestMapping("collections")
    public String collections(Account account){
   
        System.out.println(account);
        return "success";
    }

5. 自定义类型转换器

  1. 为User类添加Date birthday属性
    private Date birthday;

    public Date getBirthday() {
   
        return birthday;
    }

    public void setBirthday(Date birthday) {
   
        this.birthday = birthday;
    }
  1. jsp文件
<form action="/params/date" method="post">
    用户名:<input type="text" name="uname"><br>
    年龄:<input type="text" name="age"><br>
    生日:<input type="text" name="birthday"><br>
    <input type="submit" value="提交">
</form>
  1. controller层代码
    @RequestMapping("date")
    public String stringTodata(User user){
   
        System.out.println(user);
        return "success";
    }
  1. 测试发现如果输入生日格式为2020/4/27即可以将字符串封装成Date对象,如果输入字符串格式为2017-4-27,则封装失败

解决方案
通过自定义类型转换器来解决

  1. 实现spring框架核心包为我们提供的接口converter并且编写工具类

    /** * Created by liuzeyu on 2020/4/27. * 实现字符串转日期格式工具类 */
    public class StringToDate implements Converter<String,Date>{
         
        @Override
        public Date convert(String s) {
         
            if(s == null || s.length() == 0){
         
                throw new RuntimeException("字符串不能为空...");
            }
            DateFormat df = new SimpleDateFormat("yyyy-mm-dd");
            try {
         
                Date date = df.parse(s);
                return date;
            } catch (ParseException e) {
         
                throw new RuntimeException("日期转换失败...");
            }
    
        }
    }
    
    
  2. spring配置文件中配置,为核心包中添加一个工具类

     <!--配置自定义类型转换器-->
        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="com.liuzeyu.utils.StringToDate"></bean>
                </set>
            </property>
        </bean>
    
    
        <!--配置spring开启注解mvc的支持-->
        <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    
    1. 重新测试日期格式为2020-4-27

6. web层使用原生的servlet-api对象

  1. jsp文件
<form action="/params/servlet" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
    <input type="submit" value="提交">
</form>
  1. 编写controller代码,只需要在参数中定义请求和响应的对象即可
    /** * 测试使用原生的servlet对象 * @return */
    @RequestMapping("servlet")
    public String servlet(HttpServletRequest request, HttpServletResponse response){
   
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println(username +":"+password);
        return "success";
    }
  1. 测试结果

4. springMVC常用的注解

1. @RequestParam

作用:把请求中的指定参数名称给控制器参数赋值
属性

  1. value:请求参数名称
  2. required:请求参数中是否提供该参数,默认是true表示必须提供,如果不提供将报错。

使用实例:

<a href="anno/requestParam?username=liuzeyu">注解@RequestParam</a>
    @RequestMapping("requestParam")
    public String testRequestParam(@RequestParam(value = "username") String name,
                                   @RequestParam(value = "age",required = false) Integer age){
   
        System.out.println(name);
        return "success";
    }

其中age参数,发送请求时可以不用发送age,但必须发送?username=xxx

2. @RequestBody

**作用:**获取请求体的内容,直接使用得到的时key=xxx&value=yyy。get请求方式不适用
属性:
required:是否必须有请求体,默认为true,当为true时,get请求会报错。当请求为false时,get获取到的为null
使用实例:

<form action="anno/requestBody" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
    <input type="submit" value="提交">
</form>
<br>
<%--@RequestBody不适用于get请求--%>
<a href="anno/requestBody?username=liuzeyu&&password=80">注解@RequestBody</a>
    @RequestMapping("requestBody")
    public String testRequestBody(@RequestBody String body){
   
        System.out.println(body);
        return "success";
    }
3. @PathVariable

引出REST编码风格

什么是 rest:
REST(英文:Representational State Transfer,简称 REST)描述了一个架构样式的网络系统,
比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之
一。在目前主流的三种 Web 服务交互方案中,REST 相比于 SOAP(Simple Object Access protocol,简单
对象访问协议)以及 XML-RPC 更加简单明了,无论是对 URL 的处理还是对 Payload 的编码,REST 都倾向于用更
加简单轻量的方法设计和实现。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。
它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。
restful 的优点
它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
restful 的特性:
资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。
它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个 URI(统一
资源定位符)指向它,每种资源对应一个特定的 URI 。要
获取这个资源,访问它的 URI 就可以,因此 URI 即为每一个资源的独一无二的识别符。
表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层 (Representation)。
比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二
进制格式。
状态转化(State Transfer):每 发出一个请求,就代表了客户端和服务器的一次交互过程。
HTTP 协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,
必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以
就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET 、POST 、PUT、
DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来
删除资源。
restful 的示例:
/account/1 HTTP GET : 得到 id = 1 的 account
/account/1 HTTP DELETE: 删除 id = 1 的 account
/account/1 HTTP PUT: 更新 id = 1 的 account 
/account HTTP POST: 新增 account


作用:用于绑定url中的占位符,例如url中的/delete/{id},这个{id}就是占位符
属性

  1. value:用于指定url的占位符名称
  2. required:是否必须提供占位符

使用示例:

<a href="anno/pathVariable/10">注解@PathVariable</a>
    @RequestMapping("pathVariable/{id}")
    public String testPathVariable(@PathVariable Integer id){
   
        System.out.println(id);   //10
        return "success";
    }

4. @RequestHeader

作用:用户获取请求消息头
属性

  1. value:提供消息头名称
  2. required:是否必须有此消息头

:实际开发中并不常用。

示例:

<a href="anno/requestHeader">注解@RequestHeader</a>
    @RequestMapping("requestHeader")
    public String testRequestHeader(@RequestHeader(value = "User-Agent") String header,
                                    @RequestHeader(value = "date",required = false) String date){
   
        System.out.println(header);
        System.out.println(date);
        return "success";
    }

输出:(date并不包含在请求头中)

5. @CookieValue

作用:用于把指定的cookie名称值传入控制器的方法参数
属性

  1. value:提供指定的cookie名称
  2. required:是否必须有此cookie
<a href="anno/cookieValue">注解@CookieValue</a>
    @RequestMapping("cookieValue")
    public String testCookieValue(@CookieValue(value = "JSESSIONID",required = false) String cookieValue){
   
        System.out.println(cookieValue);
        return "success";
    }

输出:

6. @ModelAttribute

作用:该注解是springMVC 4.3之后加入的,它可以用于修饰方法和参数
属性
value:用于获取数据的key,key可以是POJO的属性名称,也可以是map结构的key。
应用场景:当表单提交数据不是完整的实体类数据时,保证没有提交的数据可以使用数据库原来的数据。
例如:
我们在更新一个用户的数据时,用户有一个字段是不允许被修改的,我们提交表单也没有该字段。该字段从数据库中获取的,于是我们可以先从数据库中获取到,之后更新到新增的到用户。
示例1:ModelAttribute 修饰方法不带返回值

<form action="anno/modelAttribute2" method="post">
    用户名:<input type="text" name="uname"><br>
    密码:<input type="text" name="age"><br>
    <input type="submit" value="提交">
</form>
    @RequestMapping("modelAttribute2")
    public String testModelAttribute2(User user){
   
        System.out.println("testModelAttribute2.....");
        System.out.println(user);
        return "success";
    }
    @ModelAttribute
    public User showUser2(String username){
   
        System.out.println("showUser2.....");
        User user = new User();
        user.setUname(username);
        user.setAge(99999);
        user.setBirthday(new Date());
        return user;
    }


输出:

示例2:ModelAttribute 修饰方法带返回值
基于Map

<form action="anno/modelAttribute1" method="post">
    用户名:<input type="text" name="uname"><br>
    密码:<input type="text" name="age"><br>
    <input type="submit" value="提交">
</form>
  /** * 注解@ModelAttribute:基于map * @param user * @return */
    @RequestMapping("modelAttribute1")
    public String testModelAttribute1(@ModelAttribute(value = "one") User user){
   
        System.out.println("testModelAttribute1.....");
        System.out.println(user);
        return "success";
    }
    //会比testModelAttribute先执行
    @ModelAttribute
    public void showUser1(String username,Map<String,User> map){
   
        System.out.println("showUser1.....");
        User user = new User();
        user.setUname(username);
        user.setAge(9999);
        user.setBirthday(new Date());
        map.put("one",user);
    }


输出:

7. @SessionAttribute

作用:用于多次执行控制方法间的参数共享
属性

  1. value:用于指定存入session的属性名称
  2. type:用于指定存入session的属性数据类型

示例

<a href="anno/sessionAttribute">sessionAttribute</a>  //存入session
<a href="anno/getSession">getSession</a>//获取session
<a href="anno/delSession">delSession</a>//删除session

加上注解@SessionAttribute可以将session共享到控制类的所有方法

 /** * Session域对象共享数据 * @param model * @return */
    @RequestMapping("sessionAttribute")
    public String testSessionAttribute(Model model){
   
        System.out.println("testSessionAttribute.....");
        model.addAttribute("msg","你好 model");
        return "success";
    }


    @RequestMapping("getSession")
    public String getSessionAttribute(ModelMap modelMap){
   
        System.out.println("getSession.....");
        String msg = (String)modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }

    @RequestMapping("delSession")
    public String delSessionAttribute(SessionStatus status){
   
        System.out.println("delSession.....");
        status.setComplete();   //删除session
        return "success";
    }

输出:

如果要想在前端页面展示,则可以开启EL表达式