SpringMVC--核心概念 / @RequestMapping注解

news2024/11/26 16:24:34

目录

1. 准备工作

1.1. 创建SpringMVC-demo02 子模块

1.2. 添加相关依赖

1.3. 设置 Maven 打包方式

1.4. 配置 web.xml 文件

1.4.1. 创建 web.xml 文件

1.4.2. 默认配置方式

1.4.3. 扩展配置方式

1.4.4. 注意点

1.5. 配置 Spring 文件

1.5.1. Thymeleaf视图解析器

1.6. 测试案例

1.7. 步骤总结

2. @RequestMapping注解

2.1. 注解功能

2.2. 注解位置

2.3. 注解value属性

2.4. 注解method属性

2.4.1. 派生注解

2.5. 注解params属性(了解)

2.6. 注解headers 属性(了解)

2.7. params 和 headers 区别

2.7.1. headers属性

2.7.2. params属性

2.8. SpringMVC支持ant风格的路径

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

2.9.1. 原始方式(非RESTful)

2.9.2. REST方式(RESTful)

2.9.3. 两者对比

2.9.4. 代码示例


1. 准备工作

让我们再回顾一遍搭建一个基本的SpringMVC项目的基本步骤 (~ ̄▽ ̄)~


1.1. 创建SpringMVC-demo02 子模块


1.2. 添加相关依赖

因为这是子模块,由于 maven 的依赖的传递性,把依赖添加在父工程的 pom 文件即可

<dependencies>
    <!-- SpringMVC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.14</version>
    </dependency>
    
    <!-- 日志 -->
    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.14</version>
        <!--<scope>test</scope>-->
    </dependency>
    
    <!-- ServletAPI -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    
    <!--Spring5和Thymeleaf整合包-->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
        <version>3.0.12.RELEASE</version>
    </dependency>
</dependencies>


1.3. 设置 Maven 打包方式

给 SpringMVC-demo02 子模块中 pom 文件设置打包方式为——war

Maven打包方式概述:

在Maven项目对象模型(POM)中,packaging元素指定了项目的构建产物类型。Maven支持多种打包方式,每种方式都适用于不同的项目和部署场景。

  • jar这是最常见的打包方式,它会将项目编译后的类文件、依赖库和项目元数据打包到一个JAR文件中。JAR文件是一种Java归档文件,可以包含多个类文件和相关资源,通常用于库和可重用组件的分发。
  • warWAR是Web Application Archive的缩写,这种打包方式用于创建Web应用程序。它会将项目打包成WAR文件,这种文件格式专门用于部署Java EE Web应用程序到Web服务器或应用服务器,如Tomcat。
  • earEAR是Enterprise Application Archive的缩写,这种打包方式用于创建企业级应用程序。EAR文件包含多个模块,如EJB(Enterprise JavaBeans)和Web应用程序,以及应用程序所需的库和配置文件。
  • pomPOM文件是Maven项目的核心,它包含了项目的配置信息。当你指定packagingpom时,意味着该项目本身不会产生任何可执行的产物,而是作为一个父POM,用于管理其子模块或提供构建逻辑。
  • maven-plugin这种打包方式用于创建Maven插件。Maven插件可以扩展Maven的功能,允许开发者编写自定义的构建步骤或任务。
  • javadoc使用这种打包方式,Maven会生成项目的Java文档,并将它们打包成JAR文件。这通常用于发布项目的API文档。

packaging元素的值被设置为war,这意味着该项目将构建一个Web应用程序,最终产物是一个WAR文件,准备部署到Web服务器上。

<?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>
    <parent>
        <groupId>com.sakurapaid.springmvc</groupId>
        <artifactId>SpringMVC</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    
    <artifactId>SpringMVC-demo02</artifactId>
    <packaging>war</packaging>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>


1.4. 配置 web.xml 文件

1.4.1. 创建 web.xml 文件

设置打包方式后,创建和 resource 文件夹同级的 webapp 文件夹

文件图标必须是要有一个小点,否则创建失效。如果创建不成功,则重复上面的步骤再来

快捷键 Ctrl+Alt+Shift+S 打开项目结构,创建 web.xml 文件

注意,设置路径是模块名(SpringMVC-demo02)下面的 src\main\webapp 下的

这个路径是需要自己手动加入的

创建成功如下图所示


配置 web.xml 文件有以下两种方式

1.4.2. 默认配置方式

在SpringMVC框架中,web.xml是用于配置Servlet容器的行为的关键文件。特别是,它用于设置DispatcherServlet,这是SpringMVC的中心组件,负责处理所有的HTTP请求并将它们分发到相应的控制器。

默认情况下,DispatcherServlet期望在一个名为springMVC-servlet.xml的XML文件中找到它的配置。这个文件应该位于Web应用程序的WEB-INF目录下。这个配置文件定义了SpringMVC的行为,例如请求映射、视图解析器和各种拦截器。

web.xml中,DispatcherServlet的注册和映射通常如下所示

<!-- 定义 Spring MVC 的前端控制器(DispatcherServlet) -->
<servlet>
    <!-- 唯一标识该 Servlet 的名称,用于后续映射配置 -->
    <servlet-name>springMVC</servlet-name>
    <!-- 指定 Spring MVC 前端控制器实现类的全限定名 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<!-- 配置 Spring MVC 前端控制器的请求映射规则 -->
<servlet-mapping>
    <!-- 引用已定义的 Servlet 名称 -->
    <servlet-name>springMVC</servlet-name>
    <!-- 设置 URL 映射模式,此处表示将所有以 "/" 开头的请求都交给该 Servlet 处理 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

这段配置告诉Servlet容器创建一个名为springMVCDispatcherServlet实例,并将其映射到所有以/开头的URL。这意味着,当用户访问任何不是JSP文件的路径时(例如/login/about等),DispatcherServlet将接管请求的处理。

  1. <servlet> 元素用于定义一个 Servlet
  • <servlet-name> 子元素:为 Servlet 提供一个唯一的名称(例如 springMVC),用于在整个 web.xml 文件中标识和引用这个 Servlet。
  • <servlet-class> 子元素:指定所使用的 Servlet 实现类的全限定名。这里指定了 Spring MVC 的核心组件 DispatcherServlet,它是 Spring MVC 的前端控制器,负责接收、解析和分发 HTTP 请求。

  1. <servlet-mapping> 元素用于将已定义的 Servlet 与特定的 URL 请求模式关联起来
  • <servlet-name> 子元素:引用前面 <servlet> 配置中定义的 Servlet 名称(例如 springMVC)。
  • <url-pattern> 子元素:设置一个 URL 映射模式,定义了哪些类型的请求应被映射到对应的 Servlet。这里使用 / 表示根路径,即所有以 / 开头的请求(例如 /home, /login, /api/users 等)都将被转发给名为 springMVC 的 DispatcherServlet 进行处理。这种方式使得 Spring MVC 可以对应用程序的所有 HTTP 请求进行统一拦截和路由。+

1.4.3. 扩展配置方式

有时,开发者可能需要自定义DispatcherServlet的行为,例如指定一个不同位置或名称的配置文件,或者控制其初始化的时机。这时,可以使用扩展配置方式来实现这些需求。

扩展配置方式在web.xml中的示例如下:

<!-- 配置Spring MVC核心控制器(DispatcherServlet) -->
<servlet>
    <servlet-name>springMVC</servlet-name>
    <!-- 指定DispatcherServlet的全限定类名 -->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <!-- 初始化参数配置 -->
    <init-param>
        <!-- 参数名:指定Spring MVC配置文件的位置 -->
        <param-name>contextConfigLocation</param-name>
        <!-- 参数值:设置Spring MVC配置文件的路径 -->
        <param-value>classpath:SpringMVC-config.xml</param-value>
    </init-param>

    <!-- 设置DispatcherServlet在应用启动时加载的优先级,值越小,优先级越高 -->
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- 配置Spring MVC核心控制器的请求映射规则 -->
<servlet-mapping>
    <!-- 与上述<servlet>标签中定义的<servlet-name>对应 -->
    <servlet-name>springMVC</servlet-name>
    <!-- URL模式:所有以'/'开头的请求都将交由该DispatcherServlet处理 -->
    <url-pattern>/</url-pattern>
</servlet-mapping>

这段配置主要完成了以下几点工作:

  1. 定义Spring MVC核心控制器(DispatcherServlet):
  • <servlet-name>:为Spring MVC核心控制器起一个别名,此处为springMVC。
  • <servlet-class>:指定Spring MVC核心控制器的全限定类名,即org.springframework.web.servlet.DispatcherServlet。
  1. 配置初始化参数:
  • <init-param>:用于设置Spring MVC核心控制器的初始化参数。
  • <param-name>:参数名为contextConfigLocation,表示Spring MVC的配置文件位置。
  • <param-value>:参数值为/springMVC-config.xml,指定了Spring MVC框架的配置文件路径。此文件包含了如视图解析器、控制器、拦截器等Spring MVC组件的配置信息。
  1. 设置Servlet加载顺序:
  • <load-on-startup>:值为1,表示在Web应用启动时,DispatcherServlet的优先级较高,将被尽早加载。数值越小,加载优先级越高。
  1. 映射请求到Spring MVC核心控制器:
  • <servlet-mapping>:定义了如何将接收到的HTTP请求映射到已定义的Servlet上。
  • <servlet-name>:引用前面定义的Spring MVC核心控制器的名称springMVC。
  • <url-pattern>:设置URL匹配模式,此处为/,意味着所有以斜杠开头的请求(即应用根目录下的所有请求)都将被该DispatcherServlet处理。这实现了将应用程序的所有请求路由至Spring MVC框架进行处理的目的。

<url-pattern> 标签的使用

<url-pattern>标签定义了DispatcherServlet处理的URL模式。有两种常见的配置:

  • <url-pattern>设置为/时,DispatcherServlet将处理所有进入应用程序的请求,除了直接指向JSP文件的请求。这是推荐的做法,因为它允许Servlet容器直接处理JSP文件,而不需要通过SpringMVC。
  • <url-pattern>设置为/*时,DispatcherServlet将处理所有请求,包括JSP文件的请求。这种配置通常用于需要对所有请求进行预处理或过滤的情况,但它可能会导致性能问题,因为即使是JSP文件的请求也会先通过SpringMVC。

通常情况下,为了确保最佳性能和行为,建议使用<url-pattern>/的配置方式。如果你有特定的需求需要处理所有类型的请求,那么可以考虑使用<url-pattern>/*,但需要确保你的应用程序能够正确地处理这些请求。


1.4.4. 注意点

如果配 web.xml 文件时,某些地方报红,可能是依赖添加没有做好,返回上述步骤检查

这个爆红是因为没有找到名为 SpringMVC-config 的 xml 文件,需要自己手动创建


1.5. 配置 Spring 文件

根据上面爆红错误提示,需要自己手动创建 spring 配置文件

记得在 resource 文件夹下创建

添加组件扫描和配置Thymeleaf视图解析器

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring核心 beans 命名空间 -->
<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">
    
    <!-- 开启组件扫描,自动发现并注册Bean到Spring容器中 -->
    <context:component-scan base-package="com.sakurapaid.mvc.controller"/>
    
    <!-- 配置Thymeleaf视图解析器,用于将控制器返回的逻辑视图名解析为实际的HTML页面 -->
    <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">
                        
                        <!-- 设置视图的前缀,例如:如果逻辑视图名为home,则实际查找的路径为/WEB-INF/templates/home.html -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        
                        <!-- 设置视图的后缀,即视图文件的扩展名 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/> <!-- 指定模板解析模式为HTML5 -->
                        <property name="characterEncoding" value="UTF-8"/> <!-- 模板的字符编码 -->
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

</beans>

1.5.1. Thymeleaf视图解析器

简单来说,Thymeleaf视图解析器在Spring MVC中的作用就是帮助你的Web应用把控制器返回的简单名字(比如“home”)变成一个完整的、带有动态内容的HTML网页。

  1. 理解“逻辑视图名”:

当你在编写Spring MVC控制器时,某个方法可能返回一个字符串,比如return "home";。这个字符串就是“逻辑视图名”,代表了你要展示的一个网页。

  1. Thymeleaf视图解析器如何工作:

Thymeleaf视图解析器就像是一个翻译官,它拿到“home”这个逻辑视图名后,会知道去哪个地方(在这个例子中是/WEB-INF/templates/home.html)找到对应的HTML模板文件。

然后,它会用Thymeleaf模板引擎打开这个HTML模板文件,像填空题一样,把控制器传过来的数据填入模板中对应的位置(模板里有特殊的标记告诉它该填在哪里)。

最后,它把填好数据的HTML文件打包成一个完整的网页,发送给用户的浏览器显示。

  1. 为什么使用Thymeleaf:

Thymeleaf使得你可以在HTML模板文件里直接写一些简单的指令(就像特殊格式的注释),告诉它如何根据数据动态生成内容。这样,你就不需要在Java代码里写复杂的字符串拼接来创建HTML了,让HTML文件更易于阅读和编写。

Thymeleaf还支持很多高级功能,如条件显示、循环遍历、表单处理等,让你的网页能更灵活地适应不同的用户需求和数据变化。

你可以简单理解为:Thymeleaf视图解析器是Spring MVC和HTML模板之间的重要桥梁,它负责将控制器的指令转化为用户看到的实际网页。


1.6. 测试案例

根据Thymeleaf视图解析器的原理及其配置,需要在 webapp/WEB-INF 的文件夹下创建

名为 templates 的文件夹,在其中创建一个 index.html 文件

(此步骤可以根据实际情况来进行配置)

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是index界面</h1>
</body>
</html>

Thymeleaf 特性

th:href 是 Thymeleaf 提供的一个属性处理器(Attribute Processor),它扩展了标准 HTML 的 href 属性。在 Thymeleaf 模板中,使用 th: 前缀的属性都是 Thymeleaf 特有的,它们会在页面渲染时处理这些属性,生成最终的动态 HTML。

th:href="@{/hello}" 具体含义如下:

  • @{...} 是 Thymeleaf 中用来构建 URL 的语法。在这个上下文中,@{/hello} 表示一个相对于当前上下文路径(context path)的 URL。
  • @{/hello} 会被解析为一个指向服务器上 /hello 资源的链接。当用户点击这个链接时,浏览器将发送请求到类似 http://yourdomain.com/context-path/hello 的地址(其中 context-path 是您的应用程序部署时的上下文路径,如果省略则直接访问 http://yourdomain.com/hello)。
  • 因为这里都是本地服务器进行测试的,所以地址为

<a th:href="@{/hello}">HelloWorld</a><br/> 

这一行 HTML 代码借助 Thymeleaf 创建了一个指向服务器上 /hello 路径的超链接,链接文字为 "HelloWorld",并在其后添加了一个换行符。当用户访问此页面并点击 "HelloWorld" 链接时,浏览器将跳转到相应服务器端处理的 /hello 资源。

在 java 文件夹下创建软件包com.sakurapaid.mvc.controller

并创建一个对应的 TestController 测试类

package com.sakurapaid.mvc.controller;

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

/**
 * TestController类用于处理前端请求。
 */
@Controller
public class TestController {
    
    /**
     * 处理根路径("/")的请求,将其重定向到index页面。
     *
     * @return 返回一个字符串"index",代表需要渲染的视图名称。
     */
    @RequestMapping("/")
    public String test(){
        return "index";
    }
}

配置本地 Tomcat 服务器

测试运行

1.7. 步骤总结

  1. Maven依赖:在pom.xml文件中,添加了SpringMVC、日志库、ServletAPI和Thymeleaf等依赖,这些是项目运行所需的库。
  2. 打包方式:通过设置<packaging>war,指定了项目最终打包成一个Web应用(WAR文件),用于部署到Web服务器。
  3. web.xml配置:在web.xml中,配置了DispatcherServlet,它是SpringMVC的核心,负责处理HTTP请求。默认配置处理所有非JSP请求,也可以通过扩展配置指定自定义的Spring配置文件和加载时机。
  4. Spring配置文件:创建了SpringMVC-config.xml,用于配置Spring的组件扫描和Thymeleaf视图解析器,这样SpringMVC就可以找到控制器和解析视图。
  5. Thymeleaf视图解析器:配置了Thymeleaf视图解析器,它会将控制器返回的视图名解析为实际的HTML页面。
  6. 测试案例:创建了一个简单的控制器TestController,它处理根路径/的请求,并返回一个名为index的视图。
  7. Tomcat服务器:配置了本地的Tomcat服务器,以便运行和测试SpringMVC应用程序。

通过这些步骤,你可以快速搭建一个基本的SpringMVC项目,并开始开发Web应用程序。

SpringMVC入门的步骤包括设置项目依赖、配置pom.xml中的packaging元素为war、创建和配置web.xml文件、创建Spring配置文件、配置Thymeleaf视图解析器、创建测试案例、配置本地服务器并运行应用程序。通过这些步骤,可以构建出一个基本的SpringMVC应用程序,为进一步的开发和学习打下坚实的基础。


2. @RequestMapping注解

2.1. 注解功能

功能概述

@RequestMapping注解在SpringMVC中扮演着非常重要的角色,它的作用是将客户端发起的HTTP请求映射到服务器端相应的处理器函数上。

简而言之,它就是一个桥梁,告诉SpringMVC如何将用户的请求和你的代码连接起来。


代码示例

让我们通过一个简单的例子来理解这个概念:

@Controller
@RequestMapping("/web")
public class MyController {

    @RequestMapping("/hello")
    public String sayHello() {
        return "hello"; // 这个方法会返回一个字符串,这个字符串是视图的名称,例如有一个名为"hello.jsp"的页面,这里就会渲染这个页面。
    }
}

在这个例子中,我们定义了一个MyController类,并用@Controller注解标识这是一个控制器。接着,我们使用@RequestMapping注解来设置请求映射。

  • @Controller告诉Spring这是一个控制器,它的主要职责是处理用户的请求。
  • @RequestMapping("/web"):这是一个类级别的注解,它定义了所有方法的基路径。这意味着,所有在此类中定义的方法,其URL路径都会以/web作为前缀。
  • @RequestMapping("/hello"):这是一个方法级别的注解,它定义了具体的方法sayHello的路径。结合类级别的路径,完整的路径就是/web/hello。当用户访问这个URL时,sayHello方法就会被调用。

处理请求

当用户在浏览器中输入http://yourserver/web/hello并发送请求时,SpringMVC框架会识别这个请求,并根据@RequestMapping注解的配置找到对应的sayHello方法来处理这个请求。

sayHello方法执行后,返回一个字符串"hello"。这个字符串是视图的名称,SpringMVC会根据这个名称找到对应的视图模板(如hello.jsp),并渲染成HTML页面返回给用户。

通过这种方式,@RequestMapping注解使得我们可以清晰地定义每个URL和服务器端方法之间的关系,从而使得Web应用的开发变得更加有序和易于管理。


2.2. 注解位置

在SpringMVC中,@RequestMapping注解用于将URL路径映射到控制器中的方法上。这个注解可以用在两个地方:控制器类上、控制器类中的方法上

  1. 类级别:当你在控制器类上使用@RequestMapping时,你为这个类中的所有方法定义了一个共同的URL前缀。这意味着,类中每个方法的URL都会以这个前缀开始。
@Controller
@RequestMapping("/test") // 类级别注解,设置前缀为 "/test"
public class RequestMappingController {
    // ...
}

在这个例子中,"/test"是所有方法的URL前缀。

  1. 方法级别:当你在控制器方法上使用@RequestMapping时,你为这个方法定义了一个具体的URL路径。这个方法的URL将是类级别前缀和方法级别路径的组合。
@Controller
@RequestMapping("/test")
public class RequestMappingController {
    // 方法级别的URL路径是 "/test/testRequestMapping"
    @RequestMapping("/testRequestMapping")
    public String testRequestMapping() {
        return "success"; // 返回视图名称
    }
}

在这个例子中,"/testRequestMapping"是方法的URL路径。结合类级别的前缀,完整的URL路径就是"/test/testRequestMapping"

当用户访问"/test/testRequestMapping"这个URL时,testRequestMapping方法会被调用,并返回一个字符串"success"。这个字符串是视图的名称,SpringMVC会根据这个名称找到并渲染相应的视图(如success.jsp),然后将这个视图作为HTTP响应发送给用户。


2.3. 注解value属性

@RequestMapping注解中的value属性用于定义URL路径与控制器方法之间的映射关系。这个属性接受一个字符串数组,每个字符串代表一个可以触发对应方法执行的URL路径。

例如,当你在控制器方法上使用@RequestMapping注解并设置value属性为{"/testRequestMapping", "/test"}时,这意味着该方法可以响应两个不同的URL路径: /testRequestMapping/test。当用户访问这两个路径中的任意一个时,testRequestMapping方法都会被调用。

在HTML模板中,使用th:href属性可以生成到这些URL路径的链接。例如:

记得使用 xmlns:th="http://www.thymeleaf.org" 命名空间

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a th:href="@{/testRequestMapping}">测试@RequestMapping的value属性-->/testRequestMapping</a><br>
    <a th:href="@{/test}">测试@RequestMapping的value属性-->/test</a><br>
</body>
</html>
@RequestMapping(value = {"/testRequestMapping", "/test"})
public String testRequestMapping(){
    return "success";
}

这里,@{/testRequestMapping}@{/test}是Thymeleaf模板引擎的语法,它们分别生成对应的URL路径。点击这些链接时,浏览器会发起请求到相应的URL,触发testRequestMapping方法的执行。

总结来说,@RequestMappingvalue属性让我们能够定义多个URL路径,这些路径都可以映射到同一个控制器方法上。这样,无论用户访问哪个路径,都能得到一致的响应处理。


2.4. 注解method属性

在Spring框架中,@RequestMapping注解是一个非常基础且重要的组件,它用于将HTTP请求映射到相应的处理器函数上。method属性是@RequestMapping注解中的一个关键部分,它决定了该映射能够接受哪些类型的HTTP请求方法。

method属性接受一个RequestMethod类型的数组,这个数组中可以包含多种请求方法,如GETPOSTPUTDELETE等。当一个HTTP请求到达时,Spring会检查请求的方法是否在method属性定义的数组中。如果请求的方法不匹配,客户端会收到一个405 Method Not Allowed错误。

例如,如果你有一个如下配置的@RequestMapping注解:

@RequestMapping(
    value = "/testRequestMapping", "/test"
    method = {RequestMethod.GET, RequestMethod.POST}
)
public String testRequestMapping() {
    return "success";
}

这意味着/testRequestMapping这个URL可以接受GETPOST两种请求方法。如果你尝试用其他方法(如PUTDELETE)请求这个URL,将会收到405 Method Not Allowed错误。


2.4.1. 派生注解

在Spring MVC框架中,为了处理不同类型的HTTP请求,提供了一系列的注解,这些注解可以帮助开发者将控制器中的方法映射到特定的URL路径上,并指定其对应的HTTP请求方式。
这些注解是@RequestMapping的派生注解,主要包括:

  • @GetMapping:用于处理HTTP GET请求。
  • @PostMapping:用于处理HTTP POST请求。
  • @PutMapping:用于处理HTTP PUT请求。
  • @DeleteMapping:用于处理HTTP DELETE请求。

  1. GET请求:通常用于请求服务器上的数据。它不应该用于产生副作用,比如修改服务器上的数据。在Spring MVC中,可以使用@GetMapping注解来处理GET请求。例子:
@GetMapping("/getData")
public String getData() {
    return "Data retrieved successfully";
}

这段代码定义了一个处理GET请求的方法,当访问/getData时,会返回一个字符串。

  1. POST请求:用于向服务器提交数据,通常会导致服务器上数据的改变或副作用。@PostMapping注解用于处理POST请求。例子:

@PostMapping("/saveData")
public String saveData(@RequestBody String data) {
    // 保存数据到服务器
    return "Data saved successfully";
}

这里,@RequestBody注解用于告诉Spring MVC将HTTP请求正文中的JSON或XML数据绑定到方法的参数上。

  1. PUT请求:类似于POST,但它通常用于更新服务器上的现有资源。@PutMapping注解用于处理PUT请求。例子:
@PutMapping("/updateData")
public String updateData(@RequestBody String data) {
    // 更新服务器上的数据
    return "Data updated successfully";
}

  1. DELETE请求:用于删除服务器上的资源。@DeleteMapping注解用于处理DELETE请求。例子:
@DeleteMapping("/deleteData")
public String deleteData() {
    // 删除服务器上的数据
    return "Data deleted successfully";
}

虽然HTTP协议定义了多种请求方法,如GET、POST、PUT、DELETE等,但通常情况下,浏览器仅支持GET和POST请求。对于PUT和DELETE等非标准HTTP方法,浏览器并不直接支持通过表单提交这些请求。为了解决这个问题,Spring提供了一个名为HiddenHttpMethodFilter的过滤器。这个过滤器允许开发者通过在表单中隐藏字段的方式来模拟PUT和DELETE请求。当表单提交到服务器时,HiddenHttpMethodFilter会读取这个隐藏字段的值,然后根据该值来决定使用哪种HTTP方法进行处理,这个内容在在RESTful部分会讲到


2.5. 注解params属性(了解)

@RequestMapping注解的params属性是一个高级特性,它允许开发者根据请求参数来精确控制请求映射的匹配规则。这个属性可以接收一个字符串数组,每个字符串定义了一个参数条件。当一个请求到达时,Spring框架会根据这些条件来判断是否应该将请求映射到相应的处理器方法上。

以下是params属性支持的四种表达式:

  1. "param":这个表达式要求请求中必须包含名为param的参数。如果请求中没有这个参数,那么即使请求的URL和HTTP方法都符合要求,请求也不会映射到注解所标注的方法上。
  2. "!param":与第一个表达式相反,这个表达式要求请求中不能包含名为param的参数。如果请求中包含了这个参数,那么请求将不会映射到方法上,即使URL和HTTP方法都匹配。
  3. "param=value":这个表达式要求请求中必须包含名为param的参数,且该参数的值必须等于value只有当请求参数的名称和值都符合条件时,请求才会映射到方法上。
  4. "param!=value":这个表达式要求请求中必须包含名为param的参数,但该参数的值不能等于value只有当请求参数的名称符合条件且值不符合条件时,请求才会映射到方法上。

代码示例:

<a th:href="@{/test(username='admin',password=123456)">测试@RequestMapping的params属性/test</a><br>
@RequestMapping(
        value = {"/testRequestMapping", "/test"},
        method = {RequestMethod.GET, RequestMethod.POST},
        params = {"username","password!=123456"}
    )	
public String testRequestMapping(){
    return "success";
}

@RequestMapping注解定义了一个请求映射规则,要求请求必须同时满足以下条件:

  • 请求的URL路径必须是/testRequestMapping或/test。
  • 请求的HTTP方法必须是GET或POST。
  • 请求必须包含username参数。
  • 请求不能包含password参数,或者请求中包含的password参数的值不能是123456。

若当前请求满足@RequestMapping注解的value和method属性,但是不满足params属性,此时页面回报错400:Parameter conditions "username, password!=123456" not met for actual request parameters: username={admin}, password={123456}


2.6. 注解headers 属性(了解)

@RequestMapping注解是Spring框架中用于处理HTTP请求映射的一个强大工具。它的headers属性允许你定义一些规则,这些规则基于客户端请求的HTTP请求头来决定哪些请求应该被映射到特定的处理方法上。

简单来说,headers属性可以让你指定一些条件,只有当请求满足这些条件时,请求才会被对应的方法处理。有四种基本的表达方式:

  1. "header"只有当请求中包含指定的header时,请求才会被处理。
  2. "!header"只有当请求中不包含指定的header时,请求才会被处理。
  3. "header=value"只有当请求中包含指定的headerheader的值为value时,请求才会被处理。
  4. "header!=value"只有当请求中包含指定的header但其值不等于value时,请求才会被处理。

如果一个请求满足了@RequestMappingvaluemethod属性,但不满足headers属性,那么这个请求将不会调用指定的方法,而是返回404错误,表示找不到对应的处理方法。

代码示例:

@Controller
@RequestMapping("/example")
public class ExampleController {

    // 只有当请求包含"Device"请求头时,这个请求才会被处理
    @RequestMapping(headers = "Device")
    public String byDevice() {
        return "This response is for devices.";
    }

    // 只有当请求不包含"Mobile"请求头时,这个请求才会被处理
    @RequestMapping(headers = "!Mobile")
    public String notMobile() {
        return "This response is not for mobile devices.";
    }

    // 只有当请求包含"Version"请求头,并且其值等于"1.0"时,这个请求才会被处理
    @RequestMapping(headers = "Version=1.0")
    public String versionOne() {
        return "This response is for version 1.0.";
    }

    // 只有当请求包含"Version"请求头,并且其值不等于"2.0"时,这个请求才会被处理
    @RequestMapping(headers = "Version!=2.0")
    public String notVersionTwo() {
        return "This response is not for version 2.0.";
    }
}

在这个例子中,我们定义了四个不同的处理方法,每个方法都通过@RequestMapping注解的headers属性来指定了不同的请求头匹配规则。当一个HTTP请求到达时,Spring框架会检查请求的请求头,并根据这些规则决定是否调用相应的处理方法。如果请求不满足任何一个方法的headers条件,那么就会返回404错误。


2.7. params 和 headers 区别

在Spring框架中,@RequestMapping注解是一个非常重要的组件,它用于将HTTP请求映射到相应的处理方法上。这个注解提供了多种属性来定义请求的匹配条件,其中包括valuemethodheaders等。valuemethod属性比较容易理解,分别用于匹配请求的URL路径和HTTP方法(如GET、POST等)。而headers属性则是用来匹配请求中的HTTP请求头(header)的。
headers属性和params属性(通常与@RequestParam注解一起使用)的主要区别在于它们匹配的内容和使用场景不同。


2.7.1. headers属性

    • 用于匹配HTTP请求头。
    • 请求头通常包含了关于请求的元数据,比如User-AgentAccept-LanguageAuthorization等。
    • 通过headers属性,可以指定一个或多个请求头以及它们的预期值,只有当请求中包含指定的请求头并且值匹配时,对应的处理方法才会被调用。
    • 例如,@RequestMapping(headers = "Device")表示只有当请求头中包含Device时,方法才会被执行。
@Controller
public class HeaderController {

    // 当请求包含"Authorization"请求头时,这个方法会被调用
    @RequestMapping(headers = "Authorization")
    public String requireAuthorization() {
        return "Welcome, authorized user!";
    }

    // 当请求不包含"Cache-Control"请求头时,这个方法会被调用
    @RequestMapping(headers = "!Cache-Control")
    public String noCacheControl() {
        return "This response should not be cached.";
    }
}

headers属性用于定义基于HTTP请求头的匹配规则。HTTP请求头是客户端发送给服务器的额外信息,比如浏览器类型、认证信息等。在Spring MVC中,你可以通过@RequestMapping注解的headers属性来指定哪些请求头和对应的值会触发特定的处理方法。


2.7.2. params属性

    • 用于匹配请求的查询参数或路径变量。
    • 查询参数是附加在URL后面的键值对,如http://example.com?param1=value1&param2=value2中的param1=value1param2=value2
    • 路径变量是映射在URL路径中的参数,如http://example.com/user/{userId}中的{userId}
    • 通过@RequestParam注解,可以获取请求中的查询参数或路径变量的值,并在处理方法中使用它们。
    • 例如,@RequestParam("param1") String param1表示获取名为param1的查询参数的值,并将其赋值给param1变量。
@Controller
public class ParamsController {

    // 当请求的URL中包含名为"userId"的查询参数时,这个方法会被调用
    @RequestMapping(params = "userId")
    public String requireUserId(@RequestParam("userId") String userId) {
        return "User ID: " + userId;
    }

    // 当请求的URL中不包含名为"debug"的查询参数时,这个方法会被调用
    @RequestMapping(params = "!debug")
    public String noDebugMode() {
        return "This action is not in debug mode.";
    }
}

params属性用于定义基于请求参数的匹配规则。请求参数通常是通过URL的查询字符串传递的,也可以是POST请求的表单数据。在Spring MVC中,你可以通过@RequestMapping注解的params属性来指定哪些参数和对应的值会触发特定的处理方法。


总结,headers属性关注的是HTTP请求的头部信息,而params属性关注的是请求的参数信息。两者都是Spring MVC中用于定义请求映射的重要工具,但它们关注的点和使用场景有所不同。希望这次解释能让你更好地理解这两者之间的区别。


2.8. SpringMVC支持ant风格的路径

在Spring MVC中,ant风格的路径是一种用于定义URL映射的模式,它允许你使用通配符来匹配URL路径的特定部分。这些通配符使得URL映射更加灵活和强大。

下面是对这些通配符的简单解释:

  1. ?:这个符号表示匹配任意单个字符。例如,book?可以匹配book1bookA等,其中问号代表了一个任意字符的位置。
  2. *:这个符号表示匹配任意的0个或多个字符。例如,*.txt可以匹配book.txtnotes.txt等,星号代表文件名的其余部分可以是任意字符。
  3. \**:这个符号表示匹配任意一层或多层目录。这是最强大的通配符,因为它可以匹配多级路径。例如,/**可以匹配任何层级的URL路径,而/folder/**可以匹配以/folder/开头的任何路径。

在使用\**时,需要注意的是,它将会匹配从配置该映射的路径开始的所有子路径。这意味着如果你有一个映射/folder/**,它将会匹配/folder/file1/folder/subfolder/file2等所有在/folder下的路径。

代码示例:

@Controller
public class AntPathController {

    // 匹配以'book'开头,后面跟着任意字符的URL
    @RequestMapping(value = "/book?", method = RequestMethod.GET)
    public String matchSingleCharacter() {
        return "This is a book with a single character after it.";
    }

    // 匹配以'files'结尾,前面可以是任意字符的URL
    @RequestMapping(value = "*files", method = RequestMethod.GET)
    public String matchFiles() {
        return "This matches any URL ending with 'files'.";
    }

    // 匹配任何层级的'admin'下的URL路径
    @RequestMapping(value = "/admin/**", method = RequestMethod.GET)
    public String matchAdminPath() {
        return "This will match any URL under the 'admin' directory.";
    }
}

在上面的例子中,我们定义了三个使用不同通配符的映射。第一个映射/book?将会匹配像/book1这样的URL;第二个映射*files将会匹配像/somefiles/anotherfiles等以files结尾的URL;而第三个映射/admin/**将会匹配任何形式的/admin下的URL,例如/admin/user/admin/settings等。


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

在Spring MVC中,路径中的占位符是一种非常有用的功能,它允许我们将动态的值嵌入到URL路径中,从而创建更加灵活和可读性更高的RESTful API。这种机制通过@RequestMapping注解的value属性中的占位符{xxx}来实现,并通过@PathVariable注解将这些占位符映射到控制器方法的参数上。

原始方式和REST方式是两种不同的URL设计方法,它们在Web开发中用于处理客户端和服务器之间的请求和响应。


2.9.1. 原始方式(非RESTful)

在原始方式中,URL通常包含了查询参数(query parameters),这些参数通过?符号附加在URL的末尾。例如:

/deleteUser?id=1

在这个例子中,id=1就是一个查询参数,它通过?符号与URL的主体部分分开。这种方式的特点如下:

  1. 可读性:对于不熟悉RESTful原则的开发者来说,可能更容易理解,因为它明确地展示了请求的目的和所需的数据。
  2. 兼容性:大多数Web服务器和API都能很好地处理这种格式的URL。
  3. 灵活性:可以通过添加多个查询参数来传递更多的信息,例如:/deleteUser?id=1&status=active。

2.9.2. REST方式(RESTful)

REST(Representational State Transfer,表述性状态转移)是一种软件架构风格,它定义了一组原则和约束,用于创建Web服务。在RESTful方式中,URL通常不包含查询参数,而是将数据作为路径的一部分。例如:

/deleteUser/1

这种方式的特点如下:

  1. 可读性:RESTful URL更加简洁,并且通过URL的路径结构传达了操作的类型(如GET、POST、PUT、DELETE等)和资源的层次结构。
  2. 资源导向:RESTful URL强调资源的概念,每个资源都有一个唯一的标识符,这使得URL更加直观和易于理解。
  3. 无状态:每个请求从客户端到服务器都应该包含执行请求所需的所有信息,服务器不会存储任何请求的状态信息。
  4. 方法明确:RESTful架构鼓励使用标准的HTTP方法(如GET、POST、PUT、DELETE等)来明确表示对资源的操作,而不是通过URL的查询参数。

2.9.3. 两者对比

  • URL结构:原始方式的URL包含查询参数,而REST方式的URL将数据作为路径的一部分。
  • 语义清晰度:RESTful URL通常更加直观,能够清晰地表达资源和操作,而非RESTful的URL则依赖于查询参数来传递信息。
  • 维护性:RESTful架构由于其清晰的结构和遵循的标准,通常更容易维护和扩展。
  • 适用场景:对于需要高度可扩展性和可维护性的复杂系统,RESTful风格更为合适。而对于简单的应用或者内部系统,原始方式可能更为直接和方便。

总的来说,RESTful风格的URL设计更加符合现代Web开发的最佳实践,它提供了一种清晰、一致和可预测的方式来设计和使用Web API。然而,在某些情况下,原始方式的URL可能更加灵活和简单。开发者应根据具体的应用场景和需求来选择最合适的方法。


2.9.4. 代码示例

  1. 首先,有一个HTML链接:
<a th:href="@{/testRest/1/admin}">测试路径中的占位符-->/testRest</a><br>

这里使用了Thymeleaf模板引擎的语法,@{...}表示这是一个URL 方式,/testRest/1/admin是基础路径,1和admin是动态参数。当这个链接被渲染时,它将会生成一个指向/testRest/1/admin的<a>标签。

  1. 接下来是Spring MVC控制器中的方法:
@RequestMapping("/testRest/{id}/{username}")
public String testRest(@PathVariable("id") String id, @PathVariable("username") String username){
    System.out.println("id:"+id+",username:"+username);
    return "success";
}

这里定义了一个映射到/testRest/{id}/{username}路径的方法。当有请求到达这个路径时,例如/testRest/1/admin,{id}和{username}占位符将会被替换为请求中的相应部分,即1和admin。 @PathVariable("id")和@PathVariable("username")注解告诉Spring MVC将这些占位符的值分别赋给id和username参数。

最终,当访问/testRest/1/admin时,控制器方法testRest会被调用,并且控制台会输出:

id:1,username:admin

这表示方法已经成功接收到了路径中的动态参数,并可以进行后续的处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1582503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

知识图谱的最新进展与未来趋势

知识图谱的最新进展与未来趋势 一、引言 在过去的几年中&#xff0c;知识图谱已经从一个前沿的研究概念发展成为现代信息技术不可或缺的一部分。作为结构化知识的存储和表示形式&#xff0c;知识图谱通过组织信息和数据提供了深刻的洞见&#xff0c;它已被广泛应用于搜索引擎优…

HarmonyOS4-学习入门知识总结

简单的组件学习&#xff1a; /*** weip 自定义控件* 自定义构建函数也是需要充电的地方&#xff0c;分全局和局部的* 全局&#xff1a;需要添加function关键字 局部&#xff1a;不加function关键字* Styles function 自定义公共样式 分全局和局部* Extends(Text) 继承模式 只…

springboot 创建子模块时 pom 配置

创建子模块 2. 修改父模块 pom 文件 添加如下内容 <packaging>pom</packaging><modules><module>mybatisconf</module></modules>3. 修改子模块 pom 文件 <parent><groupId>com.vazquez</groupId><artifactId>bo…

wangEditor 测试环境对,但是生产环境无法显示

package.json 文件版本 "wangeditor": "4.3.0"开发环境 new Editor(#${this.id});出来的数据 正式环境 new Editor(#${this.id});出来的数据 原因&#xff1a; vue.config 文件 打包策略的时候 const assetsCDN {css: [https://lf6-cdn-tos.bytecd…

python中报错“ModuleNotFoundError: No module named ‘openpyxl‘”

python中报错“ModuleNotFoundError: No module named ‘openpyxl’” 问题描述 运行python代码时&#xff0c;报错“ModuleNotFoundError: No module named ‘openpyxl’” 解决方案&#xff1a; 可能是没有安装openpyxl&#xff0c; # 安装命令 pip install openpyxl #…

如何恢复未保存或删除/丢失的Word文件?

关闭 Word 应用程序而不保存文档&#xff1f;误删Word文档&#xff1f;许多用户会在不同的情况下丢失Word文档。如果不幸遇到此类问题&#xff0c;如何恢复已删除或未保存的 Word 文档&#xff1f;有一些方法可以恢复未保存/删除的文档。此外&#xff0c;您还可以使用Word文件恢…

【USB 】Jack (Female) Type A Connectors 2 Port Mounting Peg

1. NO BACK SHIELD&#xff0c;NO ARMS&#xff0c;FRONT GROUNDING ARMS 2. BACK SHIELD&#xff0c;NO FRONT GROUNDING ARMS 3. NO BACK SHIELD&#xff0c;FRONT GROUNDING ARMS 4. BACK SHIELD&#xff0c;FRONT GROUNDING ARMS

金铲铲单机版含教程,仅支持S1\S6\S11赛季

金铲铲单机版&#xff0c;官方的单机版&#xff0c;支持S3/S6/S11赛季&#xff0c; 我自己玩了两把&#xff0c;可以加金币/加血/设置GM权限等&#xff0c; 我猜测是开发者测试版本&#xff0c; 金铲铲单机版含教程&#xff0c;仅支持S1\S6\S11赛季 网盘自动获取 链接&#xff…

基于springboot+vue实现新闻推荐系统项目【项目源码+论文说明】

基于springboot实现新闻推荐系统演示 摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了新闻推荐系统的开发全过程。通过分析企业对于新闻推荐系统的需求&#xff0c;创建了一个计算…

MySQL 优化总结

目标知识 MySQL执行流程图 MySQL 优化成本路线图 优化成本&#xff1a;硬件>系统配置>数据库表结构>SQL及索引。优化效果&#xff1a;硬件<系统配置<数据库表结构<SQL及索引。 MySQL 五大优化原则 减少数据返回&#xff1a;设置合理字段数据类型、启用压缩…

深入理解LRU缓存算法:原理、应用与优化

LRU算法&#xff08;Least Recently Used&#xff0c;最近最少使用算法&#xff09;的思想是基于"时间局部性"原理&#xff0c;即在一段时间内&#xff0c;被访问过的数据在未来仍然会被频繁访问的概率较高。 LRU 原理 LRU算法的主要思想是将最近被使用的数据保留在…

【小程序】常用方法、知识点汇总1

欢迎来到《小5讲堂》 这是《小程序》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言请求超时Markdown解析逐行显示效果文本变动事件转发…

Vue-Router入门

现在的前后端分离项目&#xff0c;后端只管数据传递&#xff0c;视图跳转的活交由前端来干了&#xff0c;vue-router就是专门来干这个活的&#xff0c;它可以让页面跳转到指定组件 组件是可复用的 Vue 实例, 把一些公共的模块抽取出来&#xff0c;然后写成单独的的工具组件或者…

Live800:理解、调节与管理客户情绪,提升客户满意度

在企业与客户的交互过程中&#xff0c;客户情绪的管理是至关重要的。一个成功的企业不仅要提供优质的产品或服务&#xff0c;还需要关注和理解客户的情绪&#xff0c;有效地调节和管理客户的情绪&#xff0c;以提升客户满意度。文章从三个方面进行深入探讨&#xff1a;理解客户…

Netty的基本架构与组件

Netty实战精髓 前言 Netty的组成部分 1、Channel 2、Callback 3、Future ChannelFuture 提供多个附件方法来允许一个或者多个 ChannelFutureListener 实例&#xff0c;这个回调方法 operationComplete() 会在操作完成时调用。 4、Event和Handler 5、EventLOOP Netty 通过触发…

Mysql底层原理十:Redo log

3.7 Redo log Redo log记录的是物理日志&#xff0c;具体就是哪个表空间&#xff0c;哪个数据页&#xff0c;哪个偏移量&#xff0c;改了几个字节&#xff0c;改成什么表空间号数据页号偏移量修改几个字节的值具体的值 3.7.1 Redo block &#xff08;批处理缓存&#xff09;…

基于SSM+Jsp+Mysql的物流管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

44.网络游戏逆向分析与漏洞攻防-角色管理功能通信分析-角色创建服务器反馈数据包分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 现在的代码都是依据数据包来写的&#xff0c;如果看不懂代码&#xff0c;就说明没看懂数据包…

程序员必须要知道的一个在线专业书网站

网站&#xff1a; https://awesome-programming-books.github.io/ https://git-scm.com/book/zh/v2 截图如下&#xff0c;可以看到&#xff0c;里面有很多数&#xff0c;可以在线看&#xff0c;免得去到处找了。

TCP挥手中TIME_WAIT存在的原因

四次挥手的一般过程如图所示&#xff1a; 在客户端收到FIN结束报文的时候不是立刻进入CLOSED状态&#xff0c;而是进入TIME_WAIT状态&#xff0c;一般等2MLS后进入关闭状态。 原因&#xff1a; 1.可靠地终止 TCP 连接。 2.保证让迟来的 TCP报文段有足够的时间被识别并丢弃。 …