1. 引言
本教程将聚焦于 Spring MVC 的一个核心概念:控制器(Controllers)。
2. 概述
首先,让我们从宏观上审视一下 Spring MVC(即模型-视图-控制器)架构中的一个核心理念:Front Controller(前端控制器)。
从高层次来看,它的主要职责包括:
- 拦截传入的请求
- 将请求中的数据(payload)转换为内部使用的数据结构。
- 将数据发送给 Model(模型)以进行进一步处理
- 从 Model 获取处理后的数据,并将其传递给 View(视图)进行渲染
下图简要展示了 Spring MVC 的高级流程:
如图所示,在架构中,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 操作的结果:
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;
}
}
我们可以在下面看到输出的一个快照:
上述结果是通过向 API 发送一个学生 ID 为 1 的 GET 请求得到的。
这里有一个小提示,*@RequestMapping* 注解是核心注解之一,我们必须深入学习才能充分利用其潜力。
7. 总结
本文探讨了在 Spring Boot 中使用控制器的基础知识,分别从传统 MVC 应用和 RESTful API 两个角度进行了阐述。
与往常一样,本文中的所有代码都可以在 GitHub 上找到。