Spring Web MVC

前言

今天来复习 Spring Web MVC 框架。它提供了一套高效、便捷的方式来构建 Web 应用程序。今天,就让我们一同深入 Spring Web MVC,从基础概念到实际应用,好好补补.


一、Spring Web MVC 是什么?

官方定义解读

根据官方描述,Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从一开始就被纳入了 Spring 框架之中。其正式名称 "Spring Web MVC" 源于它的源模块名称(spring-webmvc),不过在日常开发中,我们通常简称它为 "Spring MVC"。那么,这里提到的 Servlet 又是什么呢?简单来说,Servlet 是一种实现动态页面的技术,更准确地讲,它是一套 Java Web 开发的规范,或者说是技术标准。

打个比方,Servlet 规范就像是一份建筑蓝图,它规定了各种功能的实现方式,但要真正建成一座 "建筑",还需要有人按照这份蓝图去编写代码。目前,常见的实现了 Servlet 规范的产品有 Tomcat、Weblogic、Jetty、Jboss、WebSphere 等,这些产品都被称为 "Servlet 容器",它们的主要作用是管理程序员编写的 Servlet 类。从这里我们可以看出,Spring Web MVC 本质上是一个 Web 框架。

MVC 定义详解

要深入理解 Spring MVC,首先得搞清楚 MVC 的概念。MVC 是 Model - View - Controller 的缩写,它是软件工程中的一种软件架构设计模式,将软件系统分为模型、视图和控制器三个基本部分。

  • View(视图):这部分主要负责在应用程序中与浏览器进行交互,展示数据的资源。比如说,我们日常浏览的网页页面,那些展示商品信息、新闻内容的部分,都属于视图层。它就像是一家餐厅的服务员,负责接待顾客,将顾客需要的信息展示给他们。
  • Model(模型):作为应用程序的主体部分,模型主要用于处理程序中的数据逻辑。以餐厅为例,后厨的厨师们根据顾客的订单准备食物,这个准备食物的过程就类似于模型层处理数据逻辑。它根据前端传来的请求,对数据进行处理和运算。
  • Controller(控制器):可以把它理解为一个分发器,其作用是决定对于视图发来的请求,应该使用哪一个模型来处理,以及处理完成后跳回到哪一个视图。还拿餐厅来说,前厅的工作人员根据顾客的点餐情况,将订单传递给相应的后厨,这就是控制器的作用。它连接着视图和模型,起到了桥梁的作用。

为了更好地理解,我们再举个例子。比如去公司面试,我们到了公司之后,HR 会给我们安排会议室,并根据候选人的情况通知不同的部门来安排面试,面试结束后,由 HR 来告诉面试结果。在这个过程中,HR 就相当于 View(视图),负责接待候选人并告知结果;不同的部门就像是Controller(控制器),HR 根据候选人来选择对应的部门进行面试;而面试官则是 Model 层,负责处理面试这个事情。

Spring MVC 的本质

MVC 是一种架构设计模式,也是一种思想,而 Spring MVC 则是对 MVC 思想的具体实现,同时它还是一个 Web 框架。总结来说,Spring MVC 就是一个实现了 MVC 模式的 Web 框架。所以,我们在学习 Spring MVC 时,主要关注两个关键要点:

一是 MVC 架构模式,

二是它作为 Web 框架的特性。

实际上,我们在之前创建 Spring Boot 项目时,勾选的 Spring Web 框架,其实就是 Spring MVC 框架。可能有些同学会疑惑,之前创建的不是 Spring Boot 项目吗?怎么又和 Spring MVC 扯上关系了呢?Spring Boot 是在 2014 年发布的,而 Spring 早在 2004 年就发布了。在 Spring Boot 发布之前,当然也可以用 Spring 来实现 MVC 架构。Spring Boot 只是实现 Spring MVC 的其中一种方式。Spring Boot 可以添加很多依赖,借助这些依赖实现不同的功能,其中通过添加 Spring Web MVC 框架,就可以实现 web 功能。

打个比方,Spring Boot 就像是一个厨房,它可以添加各种 "设备"(依赖)来实现不同的功能,而做饭(实现 MVC)就是其中之一。在很久以前,没有现代意义上的厨房,人们也可以利用火和食材做饭,这就如同在 Spring Boot 出现之前,Spring 也能实现 MVC。只不过 Spring 在实现 MVC 时,结合了自身项目的特点,做了一些优化和改变。


二、学习 Spring MVC

项目准备

既然 Spring MVC 是一个 Web 框架,那么当用户在浏览器中输入 url 之后,我们的 Spring MVC 项目就需要能够感知到用户的请求,并给予响应。我们学习 Spring MVC,重点就是学习如何通过浏览器与用户程序进行交互,这主要分为以下三个方面:

  1. 建立连接:将用户(浏览器)和 Java 程序连接起来,即访问一个地址能够调用到我们的 Spring 程序。

  2. 请求:用户请求时会携带一些参数,我们需要在程序中获取这些参数,所以请求部分主要是实现获取参数的功能。

  3. 响应 :执行完业务逻辑之后,要把程序执

    java 复制代码
    import org.springframework.stereotype.Controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @RestController
    
    public class UserController {
    
        // 路由器规则注册
    
        @RequestMapping("/sayHi")
    
        public String sayHi() {
    
            return "hello,Spring MVC";
    
        }
    
    }

行的结果返回给用户,这就是响应。

比如用户去银行存款,去柜台就是建立连接;带着银行卡、身份证去存款,这就是请求;银行返回一张存折,这就是响应。对于 Spring MVC 来说,掌握了以上这三个功能,就相当于掌握了 Spring MVC 的核心。

在创建 Spring MVC 项目时,和创建 Spring Boot 项目的方式类似。我们在创建项目时,勾选 Spring Web 模块,就相当于创建了一个 Spring MVC 项目。这里需要注意的是,Spring MVC 早期还有其他的实现方式,但在本课程中我们不再进行讲解。


建立连接

在 Spring MVC 中,我们使用@RequestMapping来实现 URL 路由映射,也就是实现浏览器与程序的连接。下面我们通过一段代码来看看具体的实现方式:

在这段代码中,我们创建了一个UserController类,并在其中定义了一个sayHi方法。通过@RequestMapping("/sayHi")注解,我们将/sayHi这个 URL 路径映射到了sayHi方法上。当我们访问http://127.0.0.1:8080/sayHi时,就可以看到程序返回的数据 "hello,Spring MVC"。

@RequestMapping 注解介绍

@RequestMapping是 Spring Web MVC 应用程序中最常用的注解之一,它主要用于注册接口的路由映射。也就是说,当服务收到请求时,路径为/sayHi的请求就会调用sayHi这个方法的代码。这里涉及到一个概念叫路由映射,简单来说,就是当用户访问一个 URL 时,将用户的请求对应到程序中某个类的某个方法的过程。那么,我们为什么要在类上添加@RestController注解呢?

如果我们把@RestController去掉,再访问http://127.0.0.1:8080/sayHi,就会发现程序报了 404 错误,找不到该页面。这是因为在一个项目中,会有很多类,每个类可能又有很多方法,Spring 程序需要知道要执行哪个方法。当类加上@RestController注解后,Spring 才会去扫描这个类里面的方法是否加了@RequestMapping注解。当然,@RestController的作用不止这一点,后面会详细讲解。

@RequestMapping 使用

@RequestMapping既可以修饰类,也可以修饰方法。当它修饰类和方法时,访问的地址是类路径 + 方法路径。例如:

java 复制代码
@RequestMapping("/user")

@RestController

public class UserController {

    @RequestMapping("/sayHi")

    public String sayHi() {

        return "hello,Spring MVC";
    
    }

}

在这个例子中,类上的@RequestMapping("/user")设置了映射请求的请求路径的初始信息,方法上的@RequestMapping("/sayHi")设置了映射请求请求路径的具体信息。此时,我们访问的地址就是http://127.0.0.1:8080/user/sayHi。需要注意的是,@RequestMapping的 URL 路径最前面加不加/(斜杠)都可以,Spring 程序启动时会进行判断,如果前面没有加/,Spring 会自动拼接上一个/。另外,@RequestMapping的 URL 路径也可以是多层路径,最终访问时,依然是类路径 + 方法路径。比如:

java 复制代码
@RequestMapping("/user/m1")

@RestController

public class UserController {

    @RequestMapping("/say/hi")

    public String sayHi() {

        return "hello,Spring MVC";

    }

}

此时,访问路径就是http://127.0.0.1:8080/user/m1/say/hi

@RequestMapping 是 GET 还是 POST 请求?

我们来测试一下就知道答案了。首先,浏览器发送的请求类型默认都是 GET,通过前面的案例,我们可以看出@RequestMapping支持 GET 请求。那么对于 POST 请求呢?我们可以通过 form 表单来构造请求进行测试。创建一个test.html文件,代码如下:

html 复制代码
<!DOCTYPE html>

<html lang="en">
    
    <head>

        <meta charset="UTF-8">

        <title>Title</title>
    
    </head>

    <body>

        <form action="/user/sayHi" method="post">

        <input type="submit" value="提交">

    </form>

    </body>

</html>

将这个前端代码放在static目录下,访问方式为http://127.0.0.1:8080/test.html。从运行结果可以看出,@RequestMapping既支持 Get 请求,又支持 Post 请求。同理,它也支持其他的请求方式。那么如何指定 GET 或者 POST 类型呢?我们可以通过显式地指定@RequestMapping来接收特定类型的请求,例如:

java 复制代码
import org.springframework.stereotype.Controller;

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

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

@RestController

public class UserController {

    @RequestMapping(value = "/getRequest", method = RequestMethod.POST)

    public String sayHi() {

        return "get request...";

    }

}

在这段代码中,我们通过method = RequestMethod.POST指定了该请求只接收 POST 类型的请求。


Postman 介绍

在前面的案例中,我们发现测试后端方法时,还需要编写前端代码,这对于后端开发人员来说是一件比较麻烦的事情。随着互联网的发展,项目难度不断增加,企业也将开发人员按照功能拆分成了不同的团队,界面显示由 "前端开发工程师" 负责,业务逻辑的实现则交给 "后端开发工程师"。后端开发工程师不需要掌握前端技能,那么他们如何测试自己的程序呢?这就需要使用专业的接口测试工具,在我们的课堂中,使用的是 Postman。

下载安装 postman

我们可以通过Postman 官方下载链接进行下载,也可以使用课件中提供的Postman-win64-Setup.exe进行安装。安装后可能会提示有版本升级,点击 "Dismiss" 即可(无需升级)。

创建请求

安装完成后,打开 Postman,我们可以看到它的界面。在界面中,我们可以创建各种类型的请求,包括 GET、POST 等。例如,我们要测试前面编写的/sayHi接口,我们可以在 Postman 中创建一个 GET 请求,输入http://127.0.0.1:8080/sayHi,然后点击发送按钮,就可以看到返回的结果。

传参介绍
  • 在使用 Postman 进行测试时,我们经常需要传递参数。常见的传参方式有以下几种:
  • 普通传参 :也就是通过查询字符串来传参。在学习 HTTP 时,我们知道 URL 的格式为协议://主机:端口/路径?查询字符串,其中查询字符串就是请求的参数。例如,http://127.0.0.1:8080/param/m1?name=spring,这里的name=spring就是普通传参。
  • form - data(完整表示为:multipart/form - data):表单提交的数据,在 form 标签中加上enctyped="multipart/form - data",通常用于提交图片 / 文件。对应Content - Type: multipart/form - data。
  • x - www - form - urlencoded:form 表单,对应Content - Type: application/x - www - from - urlencoded。
  • raw:可以上传任意格式的文本,可以上传 text、json、xml、html 等。

请求

在 Spring MVC 中,学习请求部分主要是学习如何传递参数到后端以及后端如何接收参数。传递参数我们主要使用浏览器和 Postman 来模拟,后端开发人员无需过度关注如何传递参数,了解即可,实际开发中以 Postman 测试为主。

传递单个参数

在 Spring MVC 中,接收单个参数非常简单,直接在方法中使用参数即可。例如:

java 复制代码
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping("/param")

public class ParamController {

    @RequestMapping("/m1")

    public String method1(String name) {

        return "接收到参数name:" + name;

    }
    
}

我们使用浏览器发送请求http://127.0.0.1:8080/param/m1?name=spring,可以看到后端程序正确拿到了name参数的值。Spring MVC 会根据方法的参数名,找到对应的参数并赋值给方法。需要注意的是,如果参数不一致,是获取不到参数的。另外,使用基本类型来接收参数时,参数必须传(除 boolean 类型),否则会报 500 错误;类型不匹配时,会报 400 错误。例如:

java 复制代码
@RequestMapping("/m1/int")

public Object method1GetInt(int age) {

    return "接收到参数age:" + age;

}

当我们正常传递参数http://127.0.0.1:8080/param/m1/int?age=1时,浏览器响应正常;但当我们不传递age参数http://127.0.0.1:8080/param/m1/int时,浏览器会报 500 错误;当我们传递参数类型不匹配http://127.0.0.1:8080/param/m1/int?age=abc时,浏览器会报 400 错误。对于包装类型,如果不传对应参数,Spring 接收到的数据则为 null。所以在企业开发中,对于参数可能为空的数据,建议使用包装类型。

传递多个参数

接收多个参数和接收单个参数类似,直接在方法中使用多个形参即可。例如:

java 复制代码
@RequestMapping("/m2")

public Object method2(String name, String password) {

    return "接收到参数name:" + name + ", password:" + password;

}

我们使用浏览器发送请求http://127.0.0.1:8080/param/m2?name=zhangsan&password=123456,可以看到后端程序正确拿到了name和password参数的值。当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置不影响后端获取参数的结果。比如访问http://127.0.0.1:8080/param/m2?password=123456&name=zhangsan同样可以拿到正确的结果。

传递对象

当参数较多时,方法声明需要很多形参,并且每次新增参数都需要修改方法声明。这时,我们可以把这些参数封装为一个对象。Spring MVC 可以自动实现对象参数的赋值。例如,我们定义一个Person对象:

java 复制代码
public class Person {

private int id;

private String name;

private String password;

public int getId() {

    return id;

}

public void setId(int id) {

    this.id = id;
    
}

public String getName() {
    
    return name;

}

public void setName(String name) {

    this.name = name;

}

public String getPassword() {

    return password;

}

public void setPassword(String password) {

    this.password = password;

}

@Override

public String toString() {

    return "Person{" +

    "id=" + id +

    ", name='" + name + '\'' +

    ", password='" + password + '\'' +

    '}';

    }

}

然后在控制器中接收对象:

java 复制代码
@RequestMapping("/m3")

public Object method3(Person p) {

    return p.toString();

}

我们使用浏览器发送请求http://127.0.0.1:8080/param/m3?id=5&name=zhangsan&password=123456,可以看到后端程序正确拿到了Person对象里各个属性的值。

传递数组参数

在实际开发中,有时需要传递数组参数,比如批量删除操作。在 Spring MVC 中接收数组参数也较为简单。例如,要接收一个包含多个用户 ID 的数组:

java 复制代码
@RequestMapping("/m4")

public Object method4(int[] userIds) {

    StringBuilder result = new StringBuilder("接收到的用户ID数组: ");

    for (int id : userIds) {

    result.append(id).append(" ");

    }

    return result.toString();

}

使用浏览器发送请求http://127.0.0.1:8080/param/m4?userIds=1&userIds=2&userIds=3,后端程序就能正确获取并处理这个数组参数。


响应

在 Spring MVC 中,响应部分涉及如何将处理结果返回给前端。响应的方式多种多样,主要取决于业务需求和前端期望接收的数据格式。

返回字符串

前面的示例中,我们已经多次使用方法直接返回字符串作为响应。例如:

java 复制代码
@RequestMapping("/response/string")

public String responseString() {

    return "这是一个字符串响应";

}

当访问http://127.0.0.1:8080/response/string时,浏览器会直接显示 "这是一个字符串响应"。这种方式简单直接,适用于返回简单文本信息的场景。

返回 JSON 数据

在前后端分离的项目中,JSON 是一种非常常用的数据格式。Spring MVC 默认支持将对象转换为 JSON 格式返回。要返回 JSON 数据,需要确保项目中引入了 Jackson 相关依赖(在 Spring Boot 项目中,Spring Web Starter 通常已经包含了 Jackson 依赖)。假设我们有一个User类:

java 复制代码
public class User {

    private String name;

    private int age;

    // 省略getter和setter方法

}

在控制器中返回User对象:

java 复制代码
@RequestMapping("/response/json")

public User responseJson() {

    User user = new User();

    user.setName("张三");

    user.setAge(25);

    return user;

}

当访问http://127.0.0.1:8080/response/json时,浏览器会接收到类似{"name":"张三","age":25}的 JSON 数据。这里 Spring MVC 会自动使用 Jackson 库将User对象转换为 JSON 格式。


总结

  • 学习Spring MVC, 其实就是学习各种Web开发需要⽤的到注解
  • @RequestMapping: 路由映射
  • @RequestParam: 后端参数重命名
  • @RequestBody: 接收JSON类型的参数
  • @PathVariable: 接收路径参数
  • @RequestPart: 上传⽂件
  • @ResponseBody: 返回数据
  • @CookieValue: 从Cookie中获取值
  • @Controller: 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理. 默认返回视图.
  • @RestController: @ResponseBody + @Controller 返回数据

以上描述了 MVC 学习要点为建立连接(用@RequestMapping)、请求(接收多种参数)、响应。还讲解了相关注解、Postman 工具等等,但其实 MVC 的知识内容远远不止这些,还有很多知识等着我们去深究,这里只是简单入门咯,感谢阅览!!

相关推荐
木辰風6 分钟前
vue These dependencies were not found
前端·javascript·vue.js
前端安迪23 分钟前
Playwright中修改接口返回的5种方法
前端·单元测试
前端小胡兔27 分钟前
解决vue中formdata 传值为空 控制台报错SyntaxError - expected expression, got ‘<‘
前端·javascript·vue.js
IT闫37 分钟前
【SpringSecurity】——认证、注销、权限控制和注销、记住密码、自定义登入页等知识总结
spring·安全架构
uhakadotcom42 分钟前
Astro 框架:高性能内容网站开发入门
前端·面试·github
Xxxxxl1742 分钟前
CSS - 妙用Sass
前端·css·sass
林钟雪1 小时前
基于HarmonyNext的ArkTS实战案例:构建高效的图像处理应用
前端
IT、木易1 小时前
大白话html第七章HTML 与后端交互、优化网页性能
前端·html·交互
山间点烟雨1 小时前
3. 前后端实现压缩包文件下载
前端·后端·压缩包
程序猿小玉兒1 小时前
动态表头报表的绘制与导出
前端·vue.js·elementui·c#