1. 引言

本教程将聚焦于 Spring MVC 的一个核心概念:控制器(Controllers)。

2. 概述

首先,让我们从宏观上审视一下 Spring MVC(即模型-视图-控制器)架构中的一个核心理念:Front Controller(前端控制器)。

从高层次来看,它的主要职责包括:

  • 拦截传入的请求
  • 将请求中的数据(payload)转换为内部使用的数据结构。
  • 将数据发送给 Model(模型)以进行进一步处理
  • Model 获取处理后的数据,并将其传递给 View(视图)进行渲染

下图简要展示了 Spring MVC 的高级流程:

SpringMVC

如图所示,在架构中,DispatcherServlet 扮演着前端控制器的角色。

该示意图既适用于传统的 MVC 控制器,也适用于 RESTful 控制器,只是存在一些细微差别(下文将描述)。

在传统方式中,MVC 应用并非面向服务的;因此,存在一个 View Resolver(视图解析器),它会根据从 Controller(控制器)接收到的数据来渲染最终视图。

RESTful 应用则被设计为面向服务的,并返回原始数据(通常是 JSON/XML)。由于这类应用不进行任何视图渲染,因此也就没有 View Resolvers,并且 Controller 通常被期望直接通过 HTTP 响应发送数据。

接下来,我们从传统 MVC 风格的控制器开始。

3. Maven 依赖

为了在 Spring Boot 中使用 Spring MVC,我们首先需要处理 Maven 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.0.2</version>
</dependency>

要获取该库的最新版本,请查看 Maven 中央仓库

4. Spring Boot Web 配置

现在,我们来看看如何配置 Spring Boot。由于我们已经在类路径(classpath)中添加了 Thymeleaf 依赖,因此无需为它配置任何 @Bean:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

在我们的 WebConfig 中,我们需要为 Greeting 对象和 ObjectMapper 添加一个 Bean,以启用默认的 servlet:

    @Bean
    public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> enableDefaultServlet() {
        return factory -> factory.setRegisterDefaultServlet(true);
    }

    @Bean
    public Greeting greeting() {
        Greeting greeting = new Greeting();
        greeting.setMessage("Hello World !!");
        return greeting;
    }

    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }

因此,例如,如果 Controller 返回一个名为 “welcome” 的 view(视图),那么 view resolver(视图解析器)将尝试在 templates(模板)文件夹中解析一个名为 “welcome.html” 的页面。这是 Thymeleaf 默认用于搜索视图的文件夹。

5. MVC 控制器

现在,我们终于要实现 MVC 风格的控制器了。

在下面的代码中,我们返回了一个 ModelAndView 对象,它包含一个 model map(模型映射)和一个 view object(视图对象);视图解析器将利用这两部分来完成最终的视图渲染:

@Controller
@RequestMapping(value = "/test")
public class TestController {

    @GetMapping
    public ModelAndView getTestData() {
        ModelAndView mv = new ModelAndView();
        mv.setViewName("welcome");
        mv.getModel().put("data", "Welcome home man");

        return mv;
    }
}

那么,我们在这里具体做了哪些设置呢?

首先,我们创建了一个名为 TestController 的控制器,并将其映射到 “/test” 路径。在类中,我们创建了一个返回 ModelAndView 对象的方法,并将其映射到一个 GET 请求。因此,任何以 “test” 结尾的 URL 调用都会被 DispatcherServlet 路由到 TestController 中的 getTestData 方法。

当然,我们还返回了一个附带了一些模型数据的 ModelAndView 对象。

视图对象的名称被设置为 “welcome”。如上所述,View Resolver 将在 templates 文件夹中搜索一个名为 “welcome.html” 的页面。

下面我们可以看到一个示例 GET 操作的结果:

Welcome

6. REST 控制器

Spring RESTful 应用的配置与 MVC 应用的配置基本相同,唯一的区别在于它没有 View Resolvers(视图解析器)或 model map(模型映射)。

API 通常会以 XML 或 JSON 格式将原始数据返回给客户端,因此 DispatcherServlet 会绕过视图解析器,直接将数据写入 HTTP 响应体中返回。

让我们来看一个简单的 RESTful 控制器实现:

@RestController
public class RestController {

    @GetMapping(value = "/student/{studentId}")
    public Student getTestData(@PathVariable Integer studentId) {
        Student student = new Student();
        student.setName("Peter");
        student.setId(studentId);

        return student;
    }
}

我们可以在下面看到输出的一个快照:

Student Endpoint

上述结果是通过向 API 发送一个学生 ID 为 1GET 请求得到的。

这里有一个小提示,*@RequestMapping* 注解是核心注解之一,我们必须深入学习才能充分利用其潜力。

7. 总结

本文探讨了在 Spring Boot 中使用控制器的基础知识,分别从传统 MVC 应用和 RESTful API 两个角度进行了阐述。

与往常一样,本文中的所有代码都可以在 GitHub 上找到


» 下一篇: Spring MVC与Velocity