7.1 KiB
一、基础概念
Spring MVC(Spring Model-View-Controller)是 Spring Framework 中的一部分,它是一个基于 请求驱动 的 Web 框架,主要用于构建 Web 应用程序,并且遵循 MVC(模型-视图-控制器) 设计模式。它将 Web 应用的业务逻辑、用户界面和请求处理分离,使得代码更加模块化和可维护。
二、具体流程
- 客户端发起HTTP请求
客户端(浏览器、API 客户端等)向服务器发送 HTTP 请求。请求包含了目标 URL、HTTP 方法(GET、POST 等)以及可能的请求参数。 前端通过发送 HTTP 请求(通常是 AJAX 请求)到后端的 API 端点,并期望获得响应(通常是 JSON 数据)。
- 请求到达 DispatcherServlet
所有 HTTP 请求都会先到达 Spring MVC 的核心组件:DispatcherServlet。它是前端控制器,负责将请求分发给正确的处理器。DispatcherServlet 是所有请求的入口,Spring Boot 会自动配置它。
DispatcherServlet 接受所有的 HTTP 请求,根据请求 URL 和 HTTP 方法,定位匹配的控制器方法,将请求交给相应的 Handler Mapping 来匹配控制器。在请求处理前后,执行 拦截器(可选)。最终通过 View Resolver 返回一个合适的视图(对于 RESTful API,通常返回 JSON 格式的数据)。
- 查找处理器(Handler Mapping)
DispatcherServlet 根据请求的 URL 和 HTTP 方法,查找与之匹配的处理器方法(通常是一个控制器中的方法)。这是由 HandlerMapping 完成的。Spring MVC 提供了多种方式来映射 URL 到控制器方法,例如 @RequestMapping、@GetMapping 等注解。
@RestController:该注解标记的类会返回 JSON 数据。
@RequestMapping:用于映射 URL 路径和 HTTP 方法。
@GetMapping、@PostMapping 等:简化版本的 @RequestMapping。
- 执行拦截器(Interceptor)
在请求到达控制器之前,DispatcherServlet 会依次执行配置的拦截器。拦截器主要用于日志记录、安全检查、请求参数的预处理等。
preHandle:请求进入控制器方法之前。
postHandle:请求完成后,视图渲染之前。
afterCompletion:视图渲染完成后。
如果拦截器的 preHandle 方法返回 false,请求会被拦截,后续的处理不会继续进行。
- 控制器方法处理请求(Handler Execution)
DispatcherServlet 调用合适的控制器方法来处理请求。控制器方法负责处理请求的业务逻辑,并返回一个 Java 对象,这个对象会被自动转换成 JSON 格式返回给客户端。
Spring 通过 @ResponseBody 注解(或 @RestController)实现将 Java 对象自动转换为 JSON 格式。默认情况下,Spring 使用 Jackson 来将 Java 对象序列化成 JSON 数据。
@RestController:将控制器标记为返回 JSON 数据的 RESTful 控制器。
@ResponseBody:标记方法返回的数据需要直接作为响应体返回,而不是解析为视图。
@RequestParam:用于获取单个请求参数。
@PathVariable:用于从 URL 中提取变量(如 /users/{id} 中的 {id})。
- 响应返回客户端
DispatcherServlet 将处理完的结果(JSON 数据)返回给客户端。响应数据通常会包含:
状态码:如 200 OK(成功)、201 Created(资源创建成功)、404 Not Found(资源未找到)、500 Internal Server Error(服务器错误)等。
响应头:通常包括 Content-Type: application/json,表示响应体是 JSON 格式。
响应体:包含返回的数据,通常是一个 JSON 格式的对象或数组。
注:以上只适用于基于RESTful API 前后端分离的架构。
三、完整流程
在SpringMVC前面还有Tomcat容器层。客户端发起请求后,先经过Tomcat容器,根据请求的 URL 确定该请求是否是静态资源请求(如 .html、.css、.js)。如果是静态资源请求,Tomcat 会直接返回文件,而不经过 Spring MVC 的请求处理链。对于动态请求(如请求 /user 等),Tomcat 会将这些请求交给 DispatcherServlet 进行处理。
在进入DispatcherServlet前可以增加过滤器进行处理。过滤器不属于Spring部分。
Tomcat 是一个轻量级的 Web 服务器和 Servlet 容器,支持 Java Servlet 和 JSP 规范,能够处理 HTTP 请求并生成动态 Web 内容。
Servlet 是 Java 编写的服务器端程序,能够接收 HTTP 请求并生成响应,它是动态 Web 内容生成的核心技术。
Tomcat 管理 Servlet 的生命周期,并负责处理客户端的请求和返回响应。
四、重要知识点
4.1 拦截器和过滤器区别
- 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
- 拦截器只能对action请求(DispatcherServlet 映射的请求)起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问容器中的Bean(DI),而过滤器不能访问(基于spring注册的过滤器也可以访问容器中的bean)。
- 执行顺序:过滤器->拦截器
4.2 拦截器执行顺序
HandlerInterceptor 拦截器执行顺序:
- preHandle():请求处理前 按注册顺序依次执行。
- Controller:请求处理 请求到达Controller并被处理。
- postHandle():请求处理后,视图渲染前 按注册顺序逆序执行。
- afterCompletion():视图渲染后 按注册顺序逆序执行。
4.3 请求和响应体拦截器
RequestBodyAdvice, ResponseBodyAdvice主要发生在Controller执行前后:
- preHandle():请求处理前
- beforeBodyRead:请求体反序列化前
- @RequestBody:Controller方法参数绑定
- Controller:请求处理
- beforeBodyWrite():响应体序列化之前
- postHandle():请求处理后
- 视图渲染
- afterCompletion():请求结束
4.4 @Controller 和 @RestController区别
@Controller:用于定义一个 Spring MVC 控制器类。它通常用于返回视图(如 JSP 或 Thymeleaf)。
@RestController:是 @Controller 和 @ResponseBody 的组合,用于开发 RESTful API。它将方法的返回值直接写入 HTTP 响应体中,通常返回 JSON 或 XML 格式的数据。
4.5 异常处理
@ExceptionHandler:用于控制器类或方法中处理特定异常。它会捕获指定的异常并返回相应的响应(如错误页面、错误消息等)。
@ControllerAdvice:是一个全局异常处理器,用于捕获应用中所有控制器抛出的异常。
