简单了解SpringMVC

SpringMVC 概述

什么是 MVC?

MVC 是一种软件架构的思想,将软件按照模型、视图、控制器来划分

  • M:Model,模型层,指工程中的JavaBean,作用是处理数据

    JavaBean分为两类

    • 一类称为实体类 Bean:专门存储业务数据的,如 Student、User 等
    • 一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。
  • V:View,视图层,指工程中的 html 或 jsp 等页面,作用是与用户进行交互,展示数据

  • C:Controller,控制层,指工程中的 servlet,作用是接收请求和响应浏览器

  • MVC的工作流程: 用户通过视图层发送请求到服务器,在服务器中请求被 Controller 接收,Controller 调用相应的 Model 层处理请求,处理完毕将结果返回到 Controller,Controller 再根据请求处理的结果找到相应的 View 视图,渲染数据后最终响应给浏览器。
    在这里插入图片描述

什么是 SpringMVC?

  • SpringMVC 是 Spring 的一个后续产品,是 Spring 的一个子项目
  • SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Struts、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案

注意:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台 servlet

SpringMVC 的特点

  • Spring 家族原生产品,与 IOC 容器等基础设施无缝对接

  • 基于原生的 Servlet,通过了功能强大的前端控制器 DispatcherServlet,对请求和响应进行统一处理

  • 表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案

  • 代码清新简洁,大幅度提升开发效率

  • 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可

  • 性能卓著,尤其适合现代大型、超大型互联网项目要求

HelloWorld

开发环境

创建 Maven 工程

  • 创建 Maven 工程

    在这里插入图片描述

  • 设置打包方式:war

    <packaging>war</packaging>
    
  • 引入相关依赖

    <dependencies>
    	<!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.1</version>
        </dependency>
    
        <!-- 日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    
        <!-- ServletAPI -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <!--
              依赖范围
              provided:表示打成 war 包的时候,这个依赖不会一起打包
            -->
            <scope>provided</scope>
        </dependency>
    
        <!-- Spring5和Thymeleaf整合包 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
    </dependencies>
    

配置 web.xml

  • 默认配置方式

    • 位置和名称默认,就叫做默认配置(位置默认:/webapp/WEB-INF/web.xml,名称默认就是这些路径目录的名称和 web.xml)
      在这里插入图片描述

    • 如果不想手动创建,那么也是可以通过 IDEA 自动生成的:
      在这里插入图片描述

    • web.xml 代码

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
               version="4.0">
          <!-- 配置 SpringMVC 的前端控制器,对浏览器发送的请求进行统一处理 -->
          <servlet>
              <servlet-name>SpringMVC</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          </servlet>
          
          <servlet-mapping>
              <servlet-name>SpringMVC</servlet-name>
              <!--
                  设置 SpringMVC 的核心控制器所能处理的请求路径
                  /:表示当前浏览器发送的所有请求(不包括 jsp 请求路径)
                  原因:因为 jsp 的本质就是一个 Servlet(jsp 请求路径会直接找到对应的 jsp 页面然后进行跳转),所以不需要使用 DispatcherServlet 进行处理
                  如果 jsp 的请求被 SpringMVC 的 DispatcherServlet 进行处理,那么 SpringMVC 就会把 jsp 请求当做一个普通的请求进行处理,而不会去找对应的 jsp 页面
               -->
              <url-pattern>/</url-pattern>
          </servlet-mapping>
      </web-app>
      
  • 扩展配置方式

    • 可通过init-param 标签设置 SpringMVC 配置文件的位置和名称,通过 load-on-startup 标签设置 SpringMVC 前端控制器DispatcherServlet 的初始化时间(我这里将它的初始化时间提前到服务器启动的时候)
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <!-- 配置 SpringMVC 的前端控制器,对浏览器发送的请求进行统一处理 -->
        <servlet>
            <servlet-name>SpringMVC</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
            <!-- 配置 SpringMVC 配置文件的位置和名称 -->
            <init-param>
                <!-- contextConfigLocation 为固定值 -->
                <param-name>contextConfigLocation</param-name>
                <!-- 使用 "classpath:"表示从类路径查找配置文件,例如 maven工程中的 src/main/resources -->
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
    
            <!--
              将前端控制器 DispatcherServlet 的初始化时间提前到服务器启动时,然后在启动服务的时候就可以直接进行使用了
              > Spring 默认是在第一次使用的时候进行初始化
              > 如果不设置初始化时间,假设服务启动时有很多的配置需要加载,那么就会影响访问速度
            -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <!--
                设置 SpringMVC 的核心控制器所能处理的请求路径
                /:表示当前浏览器发送的所有请求(不包括 jsp 请求路径)
                原因:因为 jsp 的本质就是一个 Servlet(jsp 请求路径会直接找到对应的 jsp 页面然后进行跳转),所以不需要使用 DispatcherServlet 进行处理
                如果 jsp 的请求被 SpringMVC 的 DispatcherServlet 进行处理,那么 SpringMVC 就会把 jsp 请求当做一个普通的请求进行处理,而不会去找对应的 jsp 页面
             -->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • 标签中使用 //* 的区别

    / 所匹配的请求可以是 /login 或 .html 或 .js 或 .css 方式的请求路径,但是 / 不能匹配 .jsp 请求路径的请求,因此就可以避免在访问 jsp 页面时,该请求被 DispatcherServlet 处理,从而找不到相应的页面。

    /* 则能够匹配所有请求,例如在使用过滤器时,若需要对所有请求进行过滤,就需要使用 /* 的写法。

创建请求控制器

  • 由于前端控制器对浏览器发送的请求进行了统一的处理,但是具体的请求有不同的处理过程,因此需要创建处理具体请求的类,即请求控制器(也就是 Controller)
  • 请求控制器中的每一个处理请求的方法都被称为控制器方法
  • 因为 SpringMVC 的控制器由一个 POJO(普通的 Java 类)担任,因此需要通过 @Controller 注解将其标识为一个控制层组件,交给 Spring 的 IOC 容器管理,此时 SpringMVC 才能够识别控制器的存在
package com.laoyang.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

}

创建 SpringMVC 配置文件

  • resources 目录下创建 SpingMVC 的配置文件,写法和 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: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/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启组件扫描,需要在头部引入 context 名称空间 -->
    <context:component-scan base-package="com.laoyang.mvc.controller" />

    <!-- 配置 Thymeleaf 视图解析器 -->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <!-- 优先级 -->
        <property name="order" value="1"/>
        <!-- 字符编码 -->
        <property name="characterEncoding" value="UTF-8"/>
        <!-- 模板 -->
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <!-- 模板模型 -->
                        <property name="templateMode" value="HTML5"/>
                        <!-- 页面编码格式 -->
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

测试 HelloWorld

案例一:实现对首页的访问

  • /WEB-INF/templates 下创建 index.html 页面(名称没要求,如果没有 templates 文件夹,就先创建一个)

    <!DOCTYPE html>
    <!-- 引入 thymeleaf 的命名空间,如果不引用则无法使用 thymeleaf 的语法 -->
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>HelloWorld首页</h1>
    </body>
    </html>
    
  • 创建对应的控制器,用来实现页面的跳转

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HelloController {
        /**
         * 访问 /WEB-INF/templates下的 index.html 页面
         */
        @RequestMapping("/")
        public String index() {
            // 返回视图名称(这个名称就是我们要跳转的页面名称,前缀和后缀在配置文件中已经配置好了,所以只需要返回视图名称即可)
            return "index";
        }
    }
    
  • 测试效果

    在这里插入图片描述

案例二:通过超链接跳转到指定页面

  • /WEB-INF/templates 下创建 taget.html 页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页</title>
    </head>
    <body>
        <h1>Hello World!</h1>
    </body>
    </html>
    
  • 在 index.html 中添加一个超链接,用于测试该案例的效果

    <!DOCTYPE html>
    <!-- 引入 thymeleaf 的命名空间,如果不引用则无法使用 thymeleaf 的语法 -->
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>HelloWorld首页</h1>
    
        <h2>
            <!-- 
            如果直接使用 href="/taget",是不会加上上下文名称的
    		比如我们正常要访问的格式为:localhost:8080/上下文名称/taget
    		而使用 href="/taget" 就会变成 localhost:8080/taget
    		最后导致 404
            -->
            <a th:href="@{/taget}">访问 taget 页面</a>
        </h2>
    </body>
    </html>
    
  • 创建对应的控制器方法

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HelloController {
        /**
         * 访问 /WEB-INF/templates下的 index.html 页面
         */
        @RequestMapping("/")
        public String index() {
            // 返回视图名称
            return "index";
        }
    
        @RequestMapping("/taget")
        public String taget() {
            return "taget";
        }
    }
    
  • 测试效果

    在这里插入图片描述

    鼠标悬浮在超链接上的时候我们可以看到左下角的路径,springmvc 就是我设置的上下文名称,点击链接后就会跳转至对应的页面:

    在这里插入图片描述

运行流程(小结)

        浏览器发送请求到服务器,如果该请求符合前端控制器的 url-pattern 规则, 那么该请求就会被前端控制器 DispatcherServlet 处理。前端控制器会读取 SpringMVC 的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中 @RequestMapping 注解的 value 属性进行匹配,如果匹配成功,则该注解所标识的控制器方法就是处理请求的方法,处理请求的方法需要返回一个字符串类型的视图名称,该视图会被视图解析器进行解析,然后加上配置好的前缀和后缀组成视图的路径,通过 Thymeleaf 对视图进行渲染,最后转发到视图锁对应的页面。

@RequestMapping 注解

  • 为了整洁,创建一个新的工程来进行演示,和之前一样的东西:web.xmlspring-mvc.xmlpom.xml

  • HelloController:

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HelloController {
        /**
         * 跳转至首页
         */
        @RequestMapping("/")
        public String doIndex() {
            return "index";
        }
    }
    
  • index.html:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
    </body>
    </html>
    

@RequestMapping 注解的功能

  • @RequestMapping 注解的作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。
  • SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。

@RequestMapping 注解的位置

  • @RequestMapping 标识一个类:设置映射请求的请求路径的初始信息
  • @RequestMapping 标识一个方法:设置映射请求请求路径的具体信息
// RequestMapping部分源码
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    
}

简单理解:该注解加在类上表示当前类中的所有方法都被进行映射;添加在方法上表示当前方法被映射。

案例

  • 在创建一个 Controller,代码和 HelloController 差不多

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class RequestMappingController {
        /**
         * 跳转至主页面
         */
        @RequestMapping("/")
        public String doTaget() {
            return "taget";
        }
    }
    
  • 修改首页(index.html)

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <h1>
            <a th:href="@{/test/}">测试 @RequestMapping 注解的位置</a><br>
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的位置</a><br>
        </h1>
    </body>
    </html>
    
  • 创建要跳转的页面(taget.html)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>主页面</title>
    </head>
    <body>
        <h1>这是主页面</h1>
    </body>
    </html>
    
  • 启动 Tomcat,进行测试(此时会报错)

    因为 HelloController 控制器中也有一个处理 “/” 请求的控制器方法,所以启动 Tomcat 的时候就会导致报错(因为有重复的,导致冲突了)
    
    如果想在重复请求地址上正常进行访问,可以在类上使用 @RequestMapping 注解进行对应设置
    > 比如在 HelloController 上设置value为 "/hello",在 RequestMappingController 上设置地址为 "/test"
    > 此时再次启动 Tomcat 就不会报错了
    
    访问格式为:localhost:8080/上下文名称/hello/ 和 localhost:8080/上下文名称/test/
    > 我这里就只在 RequestMappingController 类设置了
    
  • 在 RequestMappingController 类上设置 @RequestMapping 注解,value 属性为 “/test”

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * 跳转至主页面
         */
        @RequestMapping("/")
        public String doTaget() {
            return "taget";
        }
    }
    
  • 再次启动 Tomcat 进行测试(此时就不会报错了),效果如下:

    在这里插入图片描述

  • 在点击链接测试 RequestMappingController 之前也可以先 F12 看一下链接地址是什么样的

    在这里插入图片描述

如果想要测试访问的效果,可以在 RequestMappingController 控制器中设置对应的控制器方法

@RequestMapping 注解的属性

在这里插入图片描述

红色的比较重要的,蓝色的是了解就可以了

value 属性

  • @RequestMapping 注解的 value 属性通过请求的请求地址匹配请求映射
  • @RequestMapping 注解的 value 属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求
  • @RequestMapping 注解的 value 属性必须设置,至少通过请求地址匹配请求映射

在前面的案例中,我们都是使用的单个值作为请求地址进行映射,下面就给大家演示一下多个请求地址如何进行映射

案例
  • 修改 index.html 页面

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <h1>
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的位置</a><br>
            <!-- 
      	  	  因为我们在RequestMappingController类上配置了@RequestMapping注解的value属性,所以这里使用的时候也需要加上 
    		  否则点击链接进行跳转的时候就会报 404
    		-->
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的value属性</a><br>
            <a th:href="@{/test/hello}">测试 @RequestMapping 注解的value属性</a><br>
        </h1>
    </body>
    </html>
    
  • 创建 success.html 页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>RequestMapping注解</title>
    </head>
    <body>
        <h1>Hello @RequestMapping</h1>
    </body>
    </html>
    
  • 编写对应控制器,设置多个请求地址

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * @ClassName RequestMappingController
     * @Description: @RequestMapping 注解说明
     * @Author Laoyang
     * @Date 2022/1/6 9:47
     */
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        @RequestMapping("/")
        public String doTaget() {
            return "taget";
        }
    
        /**
         * value:是一个String数组,可设置多个请求路径,当满足其中任何一个路径的时候请求映射就能直接进行匹配。
         */
        @RequestMapping(
                value = {"/success", "/hello"}
        )
        public String doSuccess() {
            return "success";
        }
    }
    
  • 启动 Tomcat 进行测试

    在这里插入图片描述

    点击红框中的两个超链接,分别查看效果

    在这里插入图片描述

    由此可见,两个超链接都可以映射到 RequestMappingController 控制器对应的控制器方法中

method 属性

  • @RequestMapping 注解的 method 属性通过请求的请求方式(get 或 post)匹配请求映射
  • @RequestMapping 注解的 method 属性是一个 RequestMethod 类型的数组,表示该请求映射能够匹配多种请求方式的请求
  • 若当前请求的请求地址满足请求映射的 value 属性,但是请求方式不满足 method 属性,则浏览器报错 405:Request method 'POST' not supported,如果想要映射成功,就需要满足这两个属性才行!
案例
  • 修改 index.html 页面

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <h1>
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的位置</a><br>
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的value属性</a><br>
            <a th:href="@{/test/hello}">测试 @RequestMapping 注解的value属性</a><br>
        </h1>
        <form method="post" th:action="@{/test/success}">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
  • 启动 Tomcat,测试效果

    在这里插入图片描述

    以上是我们没有添加 method 属性的效果。我们可以看到,这里的表单提交是不满足我们的需求的,如果我们没有在 @RequestMapping 注解中设置 method 属性,则提交的请求格式只会是 GET 类型(表单中虽然设置了 post,但是提交后还是会去找控制层中的映射方法,默认就是 GET 类型)

  • 设置 method 属性

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * method: 设置请求方式,也是一个数组,所以可以定义多个请求方式
         * 可使用 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
         */
        @RequestMapping(
                value = {"/success", "/hello"},
                method = {RequestMethod.GET}
        )
        public String doSuccess() {
            return "success";
        }
    }
    
  • 再次启动 Tomcat,测试效果

    在这里插入图片描述

    因为前端页面中设置的是 post 提交,而后端 method 设置的是 GET 方式,虽然可以找到 /success ,但是因为请求方式不同,所以就会导致映射方式不正确,最后报 405

  • 将 method 属性设置为支持 GET 和 POST

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * method: 设置请求方式,参数是一个枚举类型的数组,所以可以定义多个请求方式
         * 可使用 GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
         */
        @RequestMapping(
                value = {"/success", "/hello"},
                method = {RequestMethod.GET, RequestMethod.POST}
        )
        public String doSuccess() {
            return "success";
        }
    }
    
  • 再次启动 Tomcat,测试效果

    在这里插入图片描述

    此时点击提交按钮后,就可以正常进入到指定的页面了

派生注解说明

  • 对于处理指定请求方式的控制器方法,SpringMVC 中提供了 @RequestMapping 的派生注解:
    • 处理 get 请求的映射 --> @GetMapping
    • 处理 post 请求的映射 --> @PostMapping
    • 处理 put 请求的映射 --> @PutMapping
    • 处理 delete 请求的映射 --> @DeleteMapping
  • 常用的请求方式有 get,post,put,delete
  • 但是目前浏览器只支持 get 和 post,若在 form 表单提交时,给 method 属性设置了其他请求方式的字符串(put 或 delete),则按照默认的请求方式 get 处理
  • 若要发送 put 和 delete 请求,则需要通过 spring 提供的过滤器 HiddenHttpMethodFilter,如果硬要直接使用,就会报 405
案例
  • 在 inde.html 添加一个超链接用来测试效果

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <h1>
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的位置</a><br>
    
            <!-- 测试 value 属性 -->
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的value属性</a><br>
            <a th:href="@{/test/hello}">测试 @RequestMapping 注解的value属性</a><br>
        </h1>
    
        <!-- 测试 method 属性 -->
        <form method="post" th:action="@{/test/success}">
            <input type="submit" value="提交">
        </form>
    
        <!-- 测试派生注解 -->
        <a th:href="@{/test/doGetMapping}">测试@GetMapping注解</a>
    </body>
    </html>
    
  • 编写控制器,使用 @GetMapping 注解实现 get 方式的页面跳转

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * @RequestMapping 结合请求方式的派生注解
         * 比如:@GetMapping、@PostMapping、PutMapping、DeleteMapping
         */
        @GetMapping("/doGetMapping")
        public String doGetMapping() {
            return "success";
        }
    }
    
  • 启动Tomcat,查看效果

    在这里插入图片描述

    为了简洁,这里我就不截 index.html 页面的效果了,以上是点击超链接跳转之后的效果

  • 测试使用 put 方式提交的效果,先在 index.html 页面添加一个表单

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <h1>
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的位置</a><br>
    
            <!-- 测试 value 属性 -->
            <a th:href="@{/test/success}">测试 @RequestMapping 注解的value属性</a><br>
            <a th:href="@{/test/hello}">测试 @RequestMapping 注解的value属性</a><br>
        </h1>
    
        <!-- 测试 method 属性 -->
        <form method="post" th:action="@{/test/success}">
            <input type="submit" value="提交">
        </form>
    
        <!-- 测试派生注解 -->
        <a th:href="@{/test/doGetMapping}">测试@GetMapping注解</a>
    
        <!-- 测试put请求方式-->
        <form method="put" th:action="@{/test/testPut}">
            <input type="submit" value="put提交">
        </form>
    </body>
    </html>
    
  • 创建对应的控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        @RequestMapping(value = "/testPut", method = RequestMethod.POST)
        public String testPut() {
            return "success";
        }
    }
    
  • 测试效果

    在这里插入图片描述

    可能有人会杠了,你为什么不用 @PutMapping?那是因为浏览器只支持 post 和 get 请求,而表单中设置的是 put 提交,在提交的时候就会使用 get 方式进行处理,后端就算用了 @PutMapping,也无法进行映射(put != get)

    如果大家有兴趣,可以把控制器中的 POST 换成 GET,再次测试,就可以走通了,因为表单是使用 get 方式进行提交的(注意:这种方式只是让程序走通了,并没有实现我们最终的效果!!!后面会告诉大家如何实现 put 方式提交)。

params 属性(了解)

  • @RequestMapping 注解的 params 属性通过请求的请求参数匹配请求映射
  • @RequestMapping 注解的 params 属性是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系
  • "param":要求请求映射所匹配的请求必须携带 param 请求参数
  • "!param":要求请求映射所匹配的请求必须不能携带 param 请求参数
  • "param=value":要求请求映射所匹配的请求必须携带 param 请求参数且 param=value
  • "param!=value":要求请求映射所匹配的请求必须携带 param 请求参数但是 param!=value

注意:若当前请求满足 @RequestMapping 注解的 value 和 method 属性,但是不满足 params 属性,此时页面会报 400

案例
  • 编写控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * params = {"username"}:表示请求地址必须带一个 username 的参数
         * params = {"!username"}:表示请求地址不能带名为 username 的参数
         * params = {"username=admin"}:表示请求地址中必须带 username 参数,并且值必须是 admin
         * params = {"username!=admin"}:表示请求地址中不能带 username 参数,并且值不能是 admin
         */
        @RequestMapping( value = "/testParams", params = {"username"})
        public String testParams() {
            return "success";
        }
    }
    
  • 在前端编写超链接或表单用来测试

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <!-- 测试params属性 -->
        <a th:href="@{/test/testParams}">测试params属性</a>
        <form method="get" th:action="@{/test/testParams}">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
  • 启动 Tomcat,查看效果

    在这里插入图片描述

    因为表单和超链接在提交和跳转的时候都没有传 username 参数,所以在控制器中不能正常进行映射

  • 给表单和超链接都添加对应的参数

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <!-- 测试params属性 -->
        <a th:href="@{/test/testParams(username='admin', password='123456')}">测试params属性</a>
        <form method="get" th:action="@{/test/testParams}">
            用户名:<input  type="text" name="username"><br/>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
  • 再次测试

    在这里插入图片描述

    我这里只测试了超链接的效果,表单的效果也是一样的,就不给大家额外演示了

headers 属性(了解)

  • @RequestMapping 注解的 headers 属性通过请求的请求头信息匹配请求映射

  • @RequestMapping 注解的 headers 属性是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系

  • "header":要求请求映射所匹配的请求必须携带 header 请求头信息

  • "!header":要求请求映射所匹配的请求必须不能携带 header 请求头信息

  • "header=value":要求请求映射所匹配的请求必须携带 header 请求头信息且 header=value

  • "header!=value":要求请求映射所匹配的请求必须携带 header 请求头信息且 header!=value

  • 若当前请求满足 @RequestMapping 注解的 value 和 method 属性,但是不满足 headers 属性,此时页面显示 404 错误,即资源未找到

  • 了解:可以在页面中使用 F12 查看对应的头信息

    在这里插入图片描述

    因为我们这里是获取的是请求头信息,所以我们使用页面请求头信息中的数据,比如 Host

案例
  • 编写控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * headers 属性通过请求的请求头信息匹配请求映射
         * headers = {"header"}:表示请求地址必须带一个 header 头信息
         * headers = {"!header"}:表示请求地址不能带名为 header 的头信息
         * headers = {"header=localhost"}:表示请求地址中必须带 header 头信息,并且值必须是 localhost
         * headers = {"header!=localhost"}:表示请求地址中不能带 header 头信息,并且值不能是 localhost
         */
        @RequestMapping( value = "/testHeaders", headers = {"Host=localhost:8081"})
        public String testHeaders() {
            return "success";
        }
    }
    

    Host 默认是 localhost:8080,但是我们这里为了测试不符合要求的效果,就先设置为 localhost:8081

  • 在 index.html 页面创建一个超链接来测试

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <!-- 测试 handers 属性-->
        <a th:href="@{/test/testHeaders}">测试 handers 属性</a>
    </body>
    </html>
    
  • 启动 Tomcat,进行测试

    在这里插入图片描述

    因为我们的请求是 localhost:8080,但是控制器中设置的值是 8081,所以这里肯定是找不到的

  • 将 headers 属性设置为 8080

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * headers 属性通过请求的请求头信息匹配请求映射
         * headers = {"header"}:表示请求地址必须带一个 header 头信息
         * headers = {"!header"}:表示请求地址不能带名为 header 的头信息
         * headers = {"header=localhost"}:表示请求地址中必须带 header 头信息,并且值必须是 localhost
         * headers = {"header!=localhost"}:表示请求地址中不能带 header 头信息,并且值不能是 localhost
         */
        @RequestMapping( value = "/testHeaders", headers = {"Host=localhost:8080"})
        public String testHeaders() {
            return "success";
        }
    }
    
  • 再次测试

    在这里插入图片描述

SpringMVC 支持 ant 风格的路径

  • :表示任意的单个字符

  • *:表示任意的0个或多个字符

  • **:表示任意的一层或多层目录

    注意:在使用**时,只能使用/**/xxx的方式

案例

? 通配符的使用
  • 在 index.html 添加相关超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
    
        <!-- 测试 ant 风格路径 -->
        <a th:href="@{/test/aba/testAnt}">测试?通配符</a><br/>
    </body>
    </html>
    
  • 编写对应控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
    
        /**
         * Ant 风格的路径测试
         * ?:表示任意一个字符,比如 /a?a,我们访问的时候就可以是 /ava、/aqa、/awa 等...
         * 注意:
         * 1、路径中的 "?" 不能不写(错误写法:/aa),也不能写多个字符(错误写法:/assa)
         * 2、路径中的 "?" 不能是 /、? 字符(错误写法:/a/a、/a?a,这种格式在浏览器访问就会报 404,因为这些字符是一个特殊符号)
         * 3、"?" 前后的路径名称必须要加上(错误写法:/acc、/zsa、/qqq...等)
         */
        @RequestMapping("/a?a/testAnt")
        public String testAnt() {
            return "success";
        }
    }
    
  • 启动Tomcat进行测试

    在这里插入图片描述

* 通配符的使用
  • 在 index.html 添加相关超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <!-- 测试 ant 风格路径 -->
        <a th:href="@{/test/aa/testAnt2}">测试*通配符</a><br/>
        <a th:href="@{/test/accca/testAnt2}">测试*通配符</a><br/>
    </body>
    </html>
    
  • 编写对应控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * Ant 风格的路径测试
         * *:表示任意的0个或多个字符,我们访问的路径可以是 /aa、/ava、/aqqa、/awera 等...
         * 注意:
         * 1、路径中的 "*" 不能是 /、? 字符(错误写法:/a/a、/a?a,这种格式在浏览器访问就会报 404,因为这些字符是一个特殊符号)
         * 2、"*" 前后的路径名称必须要加上(错误写法:/acc、/zsa、/qqq...)
         */
        @RequestMapping("/a*a/testAnt2")
        public String testAnt2() {
            return "success";
        }
    }
    
  • 启动Tomcat进行测试

    在这里插入图片描述

** 通配符的使用
  • 在 index.html 添加相关超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <!-- 测试 ant 风格路径 -->
        <a th:href="@{/test/testAnt3}">测试**通配符</a><br/>
        <a th:href="@{/test/aaa/testAnt3}">测试**通配符</a><br/>
        <a th:href="@{/test/aaa/bbb/testAnt3}">测试**通配符</a><br/>
    </body>
    </html>
    
  • 编写对应控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * Ant 风格的路径测试
         * **:表示任意的一层或多层目录,我们访问的路径可以是 /** /testAnt(中间的空格不用在意,只是为了不触发注释格式加的)
         * 注意:
         * 1、路径中的 "**" 不能是 ? 字符(错误写法:/a?a,这种格式在浏览器访问就会报 404,因为这个字符是一个特殊符号)
         * 2、不能再 "**" 的前后写其它字符(错误写法:/a**a、/a**、/**a),如果在其它字符前后使用了 "**",那么就会把这两个 * 当成一个一个的 * 来进行使用(效果就和一个 * 是一样的了)
         */
        @RequestMapping("/**/testAnt3")
        public String testAnt3() {
            return "success";
        }
    }
    
  • 启动Tomcat进行测试

    在这里插入图片描述

SpringMVC 支持路径中的占位符(重点)

  • 原始方式:/deleteUser?id=1
  • rest 方式:/deleteUser/1
  • SpringMVC 路径中的占位符常用于 RESTful 风格中,当请求路径中将某些数据通过路径的方式传输到服务器中,就可以在相应的@RequestMapping 注解的 value 属性中通过占位符 {xxx} 表示传输的数据,在通过 @PathVariable 注解,将占位符所表示的数据赋值给控制器方法的形参。

案例

  • 在 index.html 页面编写超链接

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
        <h1>首页</h1>
        <!-- 测试rest方式的占位符 -->
        <a th:href="@{/test/testPath/admin/123456}">测试rest方式的占位符</a>
    </body>
    </html>
    
  • 创建对应控制器

    package com.laoyang.mvc.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    @Controller
    @RequestMapping("/test")
    public class RequestMappingController {
        /**
         * {}:
         * 注意:如果请求路径中有占位符,那么匹配地址的时候就必须有占位符,否则就会访问不到对应的请求
         */
        @RequestMapping("/testPath/{username}/{password}")
        public String testPath(@PathVariable("username") String username, @PathVariable("password") String password) {
            System.out.println(username + "---->" + password);
            return "success";
        }
    }
    
  • 启动Tomcat测试效果

    • 正确效果

      在这里插入图片描述

    • 错误效果

      在这里插入图片描述

      因为控制器中我们设置的是两个占位符,所以请求路径中也必须是两个参数,这样才能正常映射

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值