SpringMVC 入门

1. 三层架构和 MVC 开发模式

1.1 三层架构

  1. 咱们开发服务器端程序,一般都基于两种形式,一种 C/S 架构程序,一种 B/S 架构程序
  2. 使用 Java 语言基本上都是开发 B/S 架构的程序,B/S 架构又分成了三层架构
  3. 三层架构
    1. 表现层:也就是我们常说的 web 层。它负责接收客户端请求,向客户端响应结果。表现层包括展示层和控制层,控制层负责接收请求,展示层负责结果的展示。
    2. 业务层:也就是我们常说的 service 层。它负责业务逻辑处理。
    3. 持久层:也就是我们是常说的 dao 层。负责数据持久化。

1.2 MVC 开发模式

  1. MVC(Model View Controller),是一种用于设计创建 Web 应用程序表现层的模式
  2. MVC 开发模式
    1. Model:数据模型,JavaBean 的类,用来进行数据封装。
    2. View:指 JSP、HTML 用来展示数据给用户
    3. Controller:用来接收用户的请求,整个流程的控制器。

2. SpringMVC 的概述

2.1 SpringMVC 的概念

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

SpringMVC 它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求。

2.2 SpringMVC 在三层架构中的位置

在这里插入图片描述

3 SpringMVC 入门案例

3.1 需求分析

在这里插入图片描述

3.2 环境搭建

  1. 创建一个 Maven 工程

    1. 选择骨架 org.apache.maven.archetypes:maven-archetype-webapp,点击 Next

    2. 添加 Maven Property(这样可以解决 maven 项目创建过慢的问题),点击 Next

      Name:archetypeCatalog
      Value:internal
      
    3. 选择项目本地路径,点击 Finish

  2. 补全 maven 项目目录结构(此时的 maven 项目目录结构还不完整)

    1. 在 mian 包下创建 java 包,右键 Mark Derictory As --> Sources Root
    2. 在 mian 包下创建 resources 包,右键 Mark Derictory As --> Resources Root
  3. 导入坐标依赖

    <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.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>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    
  4. 配置核心控制器

    在 web.xml 配置文件配置

    <!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-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    
    
  5. 编写 springmvc.xml 的配置文件

    在 resources 中右键 new --> File,命名为 springmvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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">
        
    </beans>
    
  6. 配置一个 tomcat 服务器

    1. on update action 选择 Redeploy
    2. HTTP port 选择 80

3.3 编写程序

  1. 在 webapp 包中创建 index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>入门案例</h1>
        <a href="hello">入门程序</a>
    </body>
    </html>
    
    
  2. 在 java 包中创建 com.zt.controller 包,创建 HelloController

    /**
     * 控制器
     */
    @Controller
    public class HelloController {
        @RequestMapping(path="/hello")
        public String sayHello(){
            System.out.println("hello");
            return "success";
        }
    }
    
  3. 在 WEB-INF 包中创建 pages 包,创建 success.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h1>访问成功</h1>
    </body>
    </html>
    
  4. 配置 web.xml

    <!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-name>DispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- 配置 servlet 的初始化参数,读取 springmvc 的配置文件,创建 spring 容器 -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
            <!-- 配置 servlet 启动时加载对象 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
    
  5. 配置 springmvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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">
    
        <!-- 配置spring创建容器时要扫描的包 -->
        <context:component-scan base-package="com.zt"></context:component-scan>
        <!-- 配置视图解析器 -->
        <bean id="InternalResourceViewResolver" 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>
    

3.4 测试案例

  1. 启动 tomcat 服务器

  2. 打开浏览器,输入以下地址访问

    http://localhost/index.jsp
    
  3. 点击 “入门程序” 链接,若页面显示 “访问成功”,控制台打印 “hello",则案例运行成功

3.5 入门案例的执行过程分析

在这里插入图片描述

  1. 服务器启动,应用被加载。读取到 web.xml 中的配置,创建 DispatcherServlet 对象。
  2. 因为 DispatcherServlet 中配置了 load-on-startup 标签,所以就会加载初始化参数 springmvc.xml,并且读取 springmvc.xml 配置文件
  3. springmvc.xml 开启了注解扫描,那么 HelloController 对象就会被创建,同时配置了视图解析器,InternalResourceViewResolver 对象也会被创建
  4. 浏览器发送请求,被 DispatherServlet 捕获,该 Servlet 并不处理请求,而是把请求转发出去。转发的路径是根据请求 URL,匹配 @RequestMapping 中的内容。
  5. 匹配到了后,执行对应方法,并得到方法返回值。
  6. 根据方法的返回值,借助 InternalResourceViewResolver 找到对应的结果视图。
  7. 渲染结果视图,响应浏览器。

3.6 入门案例中涉及到的组件

在这里插入图片描述

3.6.1 DispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。

3.6.2 HandlerMapping:处理器映射器

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

3.6.3 Handler:处理器

它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由 Handler 对具体的用户请求进行处理。

3.6.4 HandlAdapter:处理器适配器

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

3.6.5 View Resolver:视图解析器

View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。

3.6.6 View:视图

SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView 等。我们最常用的视图就是 jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。

3.6.7 mvc:annotation-driven 说明

使 用 <mvc:annotation-driven> 自动加载 RequestMappingHandlerMapping(处理映射器)和 RequestMappingHandlerAdapter(处理适配器 ) ,可 用 在 SpringMVC.xml 配 置 文 件 中 使 用 <mvc:annotation-driven> 替代注解处理器和适配器的配置

3.7 RequestMapping 注解

  1. RequestMapping 的作用

    用于建立请求 URL 和处理请求方法之间的对应关系

  2. RequestMapping 的出现位置

    RequestMapping 可以作用于类和方法上:

    1. 作用在类上:第一级的访问目录
    2. 作用在方法上:第二级的访问目录
  3. RequestMapping 的属性

    1. path 指定请求路径的url
    2. value value属性和path属性是一样的
    3. mthod 指定该方法的请求方式
    4. params 指定限制请求参数的条件,要求请求参数的 key 和 value 必须和配置的一模一样。
    5. headers 发送的请求中必须包含的请求头

4. 请求参数的绑定

4.1 请求参数的绑定说明

4.1.1 绑定机制

SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的

4.1.2 绑定支持的数据类型

  1. 基本数据类型和 String 类型

  2. POJO 类型(包括实体类,以及关联的实体类)

  3. 数组和集合数据类型(List、map集合等)

4.1.3 绑定的使用要求

SpringMVC 绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。要求如下:

  1. 基本数据类型和字符串类型

    要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)

  2. POJO 类型参数

    要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。

  3. 数组和集合类型

    要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。

    给 List 集合中的元素赋值,使用下标。

    给 Map 集合中的元素赋值,使用键值对。

4.2 请求参数的绑定实例

4.2.1 基本数据类型和字符串类型作为参数

param.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="param/testParam?username=zhangsan">请求参数的绑定</a>
</body>
</html>

ParamController

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/testParam")
    public String testParam(String username){
        System.out.println(username);
        return "success";
    }
}

4.2.2 POJO 类型作为参数

Account

package com.zt.domain;

import java.io.Serializable;

public class Account implements Serializable {
    private String username;
    private String password;
    private String money;

    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 getMoney() {
        return money;
    }

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

    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", money='" + money + '\'' +
                '}';
    }
}

param.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username"><br>
        密码:<input type="text" name="password"><br>
        金额:<input type="text" name="money"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

ParamController

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account){
        System.out.println(account);
        return "success";
    }
}

4.2.3 POJO 类型包含实体类作为参数

User

public class User implements Serializable {
    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 +
                '}';
    }
}

Account

public class Account implements Serializable {
    private String username;
    private String password;
    private String money;
    private User user;

    public User getUser() {
        return user;
    }

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

    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 getMoney() {
        return money;
    }

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

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

param.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username"><br>
        密码:<input type="text" name="password"><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>
</body>
</html>

ParamController

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account){
        System.out.println(account);
        return "success";
    }
}

4.2.4 POJO 类型包含集合类型作为参数

User

public class User implements Serializable {
    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 +
                '}';
    }
}

Account

public class Account implements Serializable {
    private String username;
    private String password;
    private String money;
    private List<User> userList;
    private Map<String,User> userMap;

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    public Map<String, User> getUserMap() {
        return userMap;
    }

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    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 getMoney() {
        return money;
    }

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

    @Override
    public String toString() {
        return "Account{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", money='" + money + '\'' +
                ", userList=" + userList +
                ", userMap=" + userMap +
                '}';
    }
}

param.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="param/saveAccount" method="post">
        姓名:<input type="text" name="username"><br>
        密码:<input type="text" name="password"><br>
        金额:<input type="text" name="money"><br>
        用户姓名:<input type="text" name="userList[0].uname"><br>
        用户年龄:<input type="text" name="userList[0].age"><br>
        用户姓名:<input type="text" name="userMap['one'].uname"><br>
        用户年龄:<input type="text" name="userMap['one'].age"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

ParamController

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account){
        System.out.println(account);
        return "success";
    }
}

4.3 配置过滤器解决中文乱码问题

  1. 问题

    post 请求方式的参数变成了乱码

  2. 解决

    在 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>
    

4.4 自定义类型转换器

4.4.1 使用场景

User

public class User implements Serializable {
    private String uname;
    private Integer age;
    private Date date;

    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;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

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

param.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="param/saveUser" method="post">
        姓名:<input type="text" name="uname"><br>
        年龄:<input type="text" name="age"><br>
        出生日期:<input type="text" name="date"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

ParamController

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/saveUser")
    public String saveUser(User user){
        System.out.println(user);
        return "success";
    }
}

出现问题:此时我们如果在出生日期输入 2000-1-1,点击提交就会报错,原因是 String 类型的 2000-1-1,无法自动转换为 Date 类型,此时我们就需要自定义类型转换了

4.4.2 自定义类型转换器的实现

  1. 定义一个类,实现 Converter 接口

    public class StringToDateConverter implements Converter<String, Date> {
        @Override
        public Date convert(String source) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-HH-dd");
            if (source == null) {
                throw new RuntimeException("输入日期为空");
            } else {
                try {
                    return simpleDateFormat.parse(source);
                } catch (Exception e){
                    throw new RuntimeException("输入日期有误");
                }
            }
        }
    }
    
    
  2. 在 springmvc.xml 中配置类型转换器

    <!--注册自定义类型转换器-->
    <bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <array>
                <bean class="com.zt.utils.StringToDateConverter"></bean>
            </array>
        </property>
    </bean>
    
  3. 在 annotation-driven 标签中引用配置的类型转换服务

    <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>
    

4.5 获取 Servlet 原生的 API

SpringMVC 支持使用原始 ServletAPI 对象作为控制器方法的参数。

如下面使用 HttpServletRequest 对象:

param.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="param/testServletAPI">获取 Servlet 原生的 API</a>
</body>
</html>

ParamController

@Controller
@RequestMapping("/param")
public class ParamController {
    @RequestMapping("/testServletAPI")
    public String testServletAPI(HttpServletRequest request, HttpServletResponse response){
        System.out.println(request.getCookies());
        return "success";
    }
}

5. 常用注解

5.1 RequestParam

  1. 作用

    把请求中指定名称的参数给控制器中的形参赋值

  2. 属性

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

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
        <a href="anno/testRequestParam?uname=zhangsan">RequestParam实例</a>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testRequestParam")
        public String testRequestParam(@RequestParam(name = "uname") String username){
            System.out.println(username);
            return "success";
        }
    }
    
    

5.2 RequestBody

  1. 作用

    用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。

  2. 注意

    get 请求方式不适用,因为 get 没有请求体

  3. 属性

    1. required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值

      为 false,get 请求得到是 null。

  4. 实例

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <form action="/anno/testRequestBody" method="post">
            姓名:<input name="username" type="text"><br>
            年龄:<input name="age" type="text"><br>
            <input type="submit" value="提交" >
        </form>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testRequestBody")
        public String testRequestBody(@RequestBody String body){
            System.out.println(body);
            return "success";
        }
    }
    
    

    打印结果

    username=abc&age=20
    

5.3 PathVaribale

  1. 作用

    用于绑定 url 中的占位符。

    例如:请求 url 中 /delete/{id},这个 {id} 就是 url 占位符。

    url 支持占位符是 springmvc 支持 rest 风格 URL 的一个重要标志。

  2. 属性

    1. value:用于指定 url 中占位符名称。
    2. required:是否必须提供占位符。
  3. 实例

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="anno/testPathVaribale/100">PathVaribale实例</a>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testPathVaribale/{uid}")
        public String testPathVaribale(@PathVariable(name = "uid") String id){
            System.out.println(id);
            return "success";
        }
    }
    
    

5.4 RequestHeader

  1. 作用

    用于获取请求消息头。

  2. 属性

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

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="anno/testRequestHeader">RequestHeader实例</a>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testRequestHeader")
        public String testRequestHeader(@RequestHeader(name = "Accept") String head){
            System.out.println(head);
            return "success";
        }
    }
    
    

    打印结果

    text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    

5.5 CookieValue

  1. 作用

    用于把指定 cookie 名称的值传入控制器方法参数。

  2. 属性

    1. value:指定 cookie 的名称。
    2. required:是否必须有此 cookie。
  3. 实例

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="anno/testCookieValue">CookieValue实例</a>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testCookieValue")
        public String testCookieValue(@CookieValue(name = "JSESSIONID") String cookieValue){
            System.out.println(cookieValue);
            return "success";
        }
    }
    
    

    打印结果

    D9FEFA4C3C3AB5CD8588FA6FED7FB9AC
    

5.6 ModelAttribute

  1. 作用

    该注解可以用于修饰方法和参数。

    出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。

    出现在参数上,获取指定的数据给参数赋值。

  2. 属性

    value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。

  3. 应用场景

    当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。

  4. 实例一(基于 POJO 的使用)

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <form action="anno/testModelAttribute" method="post">
            用户姓名:<input type="text" name="uname" /><br/>
            用户年龄:<input type="text" name="age" /><br/>
            <input type="submit" value="提交" />
        </form>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testModelAttribute")
        public String testModelAttribute(User user){
            System.out.println("testModelAttribute...");
            System.out.println(user);
            return "success";
        }
    
        @ModelAttribute
        public void testShowUser(User user){
            System.out.println("testShowUser...");
            System.out.println(user);
        }
    }
    
    

    打印结果

    testShowUser...
    User{uname='123', age=20, date=null}
    testModelAttribute...
    User{uname='123', age=20, date=null}
    
  5. 实例二(基于 Map 的应用场景:ModelAttribute 修饰方法带返回值)

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <form action="anno/testModelAttribute" method="post">
            用户姓名:<input type="text" name="uname" /><br/>
            用户年龄:<input type="text" name="age" /><br/>
            <input type="submit" value="提交" />
        </form>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testModelAttribute")
        public String testModelAttribute(User user){
            System.out.println("testModelAttribute...");
            System.out.println(user);
            return "success";
        }
    
        @ModelAttribute
        public User testShowUser(String uname){
            // 模拟查询用户
            User user = new User();
            user.setUname(uname);
            user.setAge(18);
            user.setDate(new Date());
    
            System.out.println("testShowUser...");
            System.out.println(user);
            return user;
        }
    }
    
    

    打印结果

    testShowUser...
    User{uname='123', age=18, date=Tue Oct 08 15:13:46 CST 2019}
    testModelAttribute...
    User{uname='123', age=20, date=Tue Oct 08 15:13:46 CST 2019}
    
    

    分析:我们没有提交日期字段,但使用了数据库对象原有的数据

  6. 实例三(基于 Map 的应用场景:ModelAttribute 修饰方法不带返回值)

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <form action="anno/testModelAttribute" method="post">
            用户姓名:<input type="text" name="uname" /><br/>
            用户年龄:<input type="text" name="age" /><br/>
            <input type="submit" value="提交" />
        </form>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    public class AnnoController {
        @RequestMapping("/testModelAttribute")
        public String testModelAttribute(@ModelAttribute("1") User user){
            System.out.println("testModelAttribute...");
            System.out.println(user);
            return "success";
        }
    
        @ModelAttribute
        public void testShowUser(String uname, Map<String,User> map){
            // 模拟查询用户
            User user = new User();
            user.setUname(uname);
            user.setAge(18);
            user.setDate(new Date());
    
            System.out.println("testShowUser...");
            System.out.println(user);
            map.put("1",user);
        }
    }
    

    打印结果

    testShowUser...
    User{uname='123', age=18, date=Tue Oct 08 15:21:08 CST 2019}
    testModelAttribute...
    User{uname='123', age=20, date=Tue Oct 08 15:21:08 CST 2019}
    

    分析:我们没有提交日期字段,但使用了数据库对象原有的数据

5.7 SessionAttribute

  1. 作用

    用于多次执行控制器方法间的参数共享

  2. 属性

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

    anno.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="anno/testSetSessionAttribute">testSetSessionAttribute</a>
        <a href="anno/testGetSessionAttribute">testGetSessionAttribute</a>
        <a href="anno/testCleanSessionAttribute">testCleanSessionAttribute</a>
    </body>
    </html>
    
    

    AnnoController

    @Controller
    @RequestMapping("/anno")
    @SessionAttributes(value = "msg")
    public class AnnoController {
        @RequestMapping("/testSetSessionAttribute")
        public String testSetSessionAttribute(Model model){
            model.addAttribute("msg","123");
            return "success";
        }
    
        @RequestMapping("/testGetSessionAttribute")
        public String testGetSessionAttribute(ModelMap model){
            System.out.println(model.get("msg"));
            return "success";
        }
        
        @RequestMapping("/testCleanSessionAttribute")
        public String testCleanSessionAttribute(SessionStatus sessionStatus){
            sessionStatus.setComplete();
            return "success";
        }
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bm1998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值