SpringMVC知识点总结
目录
SpringMVC处理流程
什么是DispatcherServlet
为什么需要DispatcherServlet
工作流程:请求的生命周期
什么是Handler Mapping
一、核心概念:为什么需要 HandlerMapping?
二、工作原理:请求匹配流程
三、常见 HandlerMapping 实现类
什么是Handler Adapter
一、核心概念:为什么需要 HandlerAdapter?
二、工作流程:请求到处理器的适配过程
什么是View Resolver
一、核心概念:为什么需要 View Resolver?
二、工作流程:逻辑视图名 → 实际视图对象
什么是ModelAndView
使用 ModelAndView 的优点
什么是@ModelAttribute注解
@ModelAttribute 的使用场景
什么是@RequestParam注解
什么是 @PathVariable 注解
什么是SpringMVC的拦截器
一、拦截器的核心作用
二、拦截器的工作流程
三、拦截器的实现方式
什么是SpringMVC的异常处理机制
使用 @ControllerAdvice + @ExceptionHandler
什么是 Spring MVC 的 REST 支持
一、核心特性与优势
如何在 Spring MVC 中处理 JSON 数据
接收 JSON 数据
返回 JSON 数据
什么是@RestController注解
如何在 Spring MVC 中实现跨域资源共享(CORS)
一、全局配置(推荐)
二、控制器级别配置
三、方法级别配置
如何在 Spring MVC 中使@ExceptionHandler 注解
一、基本用法:在控制器内处理特定异常
二、全局异常处理:使用 @ControllerAdvice
SpringMVC处理流程
SpringMVC是Spring框架中的一个模块用于构建基于Web的应用程序。遵循Model-View-Controller的设计模式,将业务逻辑、用户界面和数据分离。
处理流程
- 用户请求:客户端向服务器发送 HTTP 请求。
- 前端控制器:DispatcherServlet 作为前端控制器,接收所有请求。
- 处理器映射:DispatcherServlet 通过 HandlerMapping 找到处理请求的 Handler(即 Controller 中的方法)。
- 处理器适配器:通过 HandlerAdapter 调用 Handler。
- 处理器处理请求:Handler 处理请求,并返回一个 ModelAndView 对象。
- 视图解析器:DispatcherServlet 通过 ViewResolver 解析 ModelAndView 中的逻辑视图名,得到实际的 View。
- 视图渲染:View 将模型数据渲染为具体的视图(如 JSP、JSON 等)。
- 响应客户端:将渲染结果返回给客户端。
核心组件
- DispatcherServlet:前端控制器,负责接收请求、协调组件处理请求和返回响应。
- HandlerMapping:处理器映射器,根据请求找到对应的 Handler。
- HandlerAdapter:处理器适配器,调用 Handler。
- Handler:处理器,即 Controller 中的方法,负责处理请求。
- ViewResolver:视图解析器,将逻辑视图名解析为实际的 View。
- View:视图,负责渲染模型数据。
什么是DispatcherServlet
DispatcherServlet
是 SpringMVC 框架的核心组件,作为整个请求处理流程的中央调度器(Front Controller),负责接收所有 HTTP 请求并协调各个组件完成请求的处理和响应。
为什么需要DispatcherServlet
1.统一入口
所有请求(如 /user/list
、/order/create
)都由 DispatcherServlet
接收,避免每个控制器单独处理 HTTP 连接。
2.职责分离
DispatcherServlet
不处理具体业务逻辑,仅负责:
- 路由请求到合适的控制器方法
- 管理请求处理流程中的组件协作
- 返回最终响应给客户端
3.遵循 MVC 模式
将请求处理、业务逻辑和视图渲染分离,提高代码可维护性。
工作流程:请求的生命周期
当客户端发送请求时,DispatcherServlet
的处理流程如下:
- 接收请求 → 所有请求首先到达
DispatcherServlet
。 - 映射处理器 → 通过
HandlerMapping
找到处理该请求的控制器方法(Handler)。 - 调用处理器 → 通过
HandlerAdapter
调用控制器方法。 - 处理业务逻辑 → 控制器方法执行并返回
ModelAndView
。 - 解析视图 → 通过
ViewResolver
将逻辑视图名解析为具体视图(如 JSP、JSON)。 - 渲染视图 → 将模型数据填充到视图中并返回响应。
什么是Handler Mapping
HandlerMapping
是 SpringMVC 框架中的核心组件之一,负责将 HTTP 请求映射到对应的处理器(Handler),即控制器(Controller)中的方法。
一、核心概念:为什么需要 HandlerMapping?
-
请求路由
当客户端发送请求(如GET /user/list
)时,HandlerMapping
需确定由哪个控制器方法处理该请求。 -
解耦 URL 与处理器
通过配置或注解,将 URL 模式(如/user/*
)与处理器绑定,无需硬编码映射关系。 -
支持多种映射策略
可根据路径、请求方法、请求参数等条件进行复杂匹配。
二、工作原理:请求匹配流程
当 DispatcherServlet
接收到请求时,HandlerMapping
的工作流程如下:
- 提取请求信息:从 HTTP 请求中获取 URL、请求方法(GET/POST)、请求参数等。
- 匹配处理器:根据配置的映射规则,找到对应的处理器(如
UserController.listUsers()
方法)。 - 返回 HandlerExecutionChain:包含处理器对象和拦截器列表。
- 执行拦截器:在处理器执行前后,执行注册的拦截器逻辑。
三、常见 HandlerMapping 实现类
SpringMVC 提供多种 HandlerMapping
实现,支持不同的映射方式:
1. RequestMappingHandlerMapping(最常用)
- 支持注解:处理
@RequestMapping
、@GetMapping
、@PostMapping
等注解。 - 匹配规则:
- 根据 URL 路径(如
/user/{id}
) - 请求方法(GET/POST/PUT/DELETE)
- 请求参数(如
?action=edit
) - 请求头(如
Content-Type
)
- 根据 URL 路径(如
2. SimpleUrlHandlerMapping
- 基于 URL 路径映射:通过配置文件或 Java 代码显式定义 URL 与处理器的映射关系。
- 适用场景:静态资源映射、遗留系统集成。
3. BeanNameUrlHandlerMapping
- 按 Bean 名称映射:将 URL 映射到 Bean 名称以
/
开头的 Bean。 - 示例:若 Bean 名称为
/userController
,则映射到/userController
路径。
什么是Handler Adapter
HandlerAdapter
是 SpringMVC 框架中的核心组件之一,负责 ** 调用具体的处理器(Handler)** 并处理其返回值。由于 SpringMVC 支持多种处理器类型(如注解方法、实现 Controller
接口的类),HandlerAdapter
的作用是将不同类型的处理器统一适配为可执行的标准接口。
一、核心概念:为什么需要 HandlerAdapter?
-
统一调用接口
不同类型的处理器(如@RequestMapping
注解的方法、实现Controller
接口的类)具有不同的调用方式。HandlerAdapter
将它们统一为handle()
方法,使DispatcherServlet
无需关心具体调用细节。 -
解耦处理器类型
处理器的实现方式(如注解驱动、接口驱动)可以灵活变化,只需提供对应的HandlerAdapter
实现即可。 -
参数解析与返回值处理
负责解析 HTTP 请求参数到处理器方法参数,并将处理器返回值转换为ModelAndView
或其他响应格式。
二、工作流程:请求到处理器的适配过程
当 DispatcherServlet
通过 HandlerMapping
找到匹配的处理器后,HandlerAdapter
的工作流程如下:
- 检查支持性:
DispatcherServlet
调用supports()
方法,确认当前HandlerAdapter
是否支持该处理器类型。 - 调用处理器:调用
handle()
方法,执行处理器逻辑并返回ModelAndView
。 - 处理返回值:将处理器返回的原始数据(如
String
、User
对象)转换为ModelAndView
或直接写入响应。
什么是View Resolver
在 SpringMVC 中,View Resolver(视图解析器) 是负责将控制器返回的逻辑视图名(如 "user/list"
)解析为实际视图对象(如 JSP、Thymeleaf 模板或 JSON 转换器)的组件。它是连接控制器逻辑和视图渲染的桥梁,使控制器无需关心具体的视图实现细节。
一、核心概念:为什么需要 View Resolver?
-
解耦视图实现
控制器只需返回逻辑视图名(如"success"
),无需指定具体的视图技术(如 JSP、Thymeleaf),实现了业务逻辑与视图渲染的分离。 -
统一视图处理流程
DispatcherServlet 通过 View Resolver 统一处理所有视图,简化了请求处理流程。 -
支持多种视图技术
同一应用中可同时使用不同的视图技术(如 JSP、Freemarker、JSON),通过不同的 View Resolver 实现切换。
二、工作流程:逻辑视图名 → 实际视图对象
当控制器返回 ModelAndView
时,View Resolver 的工作流程如下:
- 获取逻辑视图名:从
ModelAndView
中提取逻辑视图名(如"user/list"
)。 - 解析视图对象:View Resolver 根据配置规则,将逻辑视图名转换为实际的视图对象(如
JstlView
、ThymeleafView
)。 - 视图渲染:调用视图对象的
render()
方法,将模型数据填充到视图模板中,并输出响应。
什么是ModelAndView
ModelAndView
用于封装模型数据和视图信息。它允许控制器方法返回一个对象,该对象包含视图名称和模型数据,从而将数据传递给视图进行渲染。
ModelAndView
主要解决两个问题:
- 携带数据:将控制器处理后的业务数据(模型)传递给视图。
- 指定视图:告诉框架应该使用哪个视图来渲染数据。
其本质是一个容器,包含两个关键部分:
- Model:存储视图需要展示的数据(如 Map、对象等)。
- View:指定视图的逻辑名称或具体实现,用于渲染数据。
使用 ModelAndView
的优点
- 清晰分离模型和视图:将模型数据和视图信息封装在一个对象中,使得控制器方法的返回值更加清晰和结构化。
- 灵活性:可以在一个地方设置视图和模型数据,便于维护和修改。
- 简化代码:通过返回
ModelAndView
对象,可以避免在控制器方法中显式设置模型和视图。
什么是@ModelAttribute注解
@ModelAttribute
注解是 Spring MVC 中用于绑定请求参数到模型对象的注解。它可以用于方法参数、方法和控制器类中,以便将请求中的数据绑定到模型对象,并将该对象添加到模型中,以便在视图中使用。
@ModelAttribute
的使用场景
- 方法参数:用于绑定请求参数到方法参数,并将该参数添加到模型中。
- 方法:用于在处理请求之前准备模型数据。通常用于在处理请求之前初始化一些公共数据。
- 控制器类:用于在所有请求处理方法之前初始化模型数据。
什么是@RequestParam注解
@RequestParam
注解是 Spring MVC 中用于将请求参数绑定到处理方法的参数上的注解。它可以用于从 URL 查询参数、表单数据或其他请求参数中提取值,并将这些值传递给控制器方法的参数。
- 参数说明:
value
或name
:请求参数的名称(必填)。required
:参数是否必须(默认true
)。defaultValue
:参数缺失时的默认值。
@GetMapping("/example")
public String handleRequest(@RequestParam("paramName") String paramValue,@RequestParam Integer age) {// 使用 paramValue 和 age 参数return "result";
}
什么是 @PathVariable 注解
@PathVariable
注解是 Spring MVC 中用于将 URL 路径中的变量绑定到处理方法的参数上的注解。它允许你从 URL 路径中提取参数,并将这些参数传递给控制器方法,从而实现更加动态和灵活的 URL 路由。
什么是SpringMVC的拦截器
在 Spring MVC 中,拦截器(Interceptor) 是一种特殊的组件,用于在请求处理的关键节点插入自定义逻辑。它类似于 Servlet 规范中的 Filter,但功能更强大、更灵活,是 AOP(面向切面编程)思想的典型应用。
一、拦截器的核心作用
- 请求预处理:在控制器方法执行前执行特定逻辑(如身份验证、日志记录)。
- 请求后处理:在控制器方法执行后、视图渲染前执行逻辑(如修改响应数据)。
- 完成后处理:在整个请求处理完成后执行清理工作(如释放资源)。
拦截器允许开发者在不修改控制器代码的前提下,对请求进行全局或局部的增强处理。
二、拦截器的工作流程
当客户端发送请求时,拦截器的执行流程如下:
- 请求进入 DispatcherServlet。
- 预处理(preHandle):按顺序执行拦截器链的
preHandle
方法。若任一拦截器返回false
,则终止请求处理,直接返回响应。 - 执行控制器方法:所有拦截器的
preHandle
均返回true
时执行。 - 后处理(postHandle):按拦截器逆序执行
postHandle
,可修改ModelAndView
。 - 完成后处理(afterCompletion):无论请求是否成功,均按逆序执行,用于资源清理。
三、拦截器的实现方式
Spring MVC 的拦截器通过实现 HandlerInterceptor
接口来定义。这个接口包含三个主要方法:
preHandle
:在请求处理之前执行。返回true
表示继续处理请求,返回false
表示中止请求。postHandle
:在请求处理之后、视图渲染之前执行。可以修改视图模型数据。afterCompletion
:在整个请求完成之后(包括视图渲染之后)执行。通常用于资源清理。
什么是SpringMVC的异常处理机制
在 Spring MVC 中,异常处理机制用于统一捕获和处理控制器层抛出的异常,避免直接将异常堆栈暴露给客户端,同时提供友好的错误响应。
使用 @ControllerAdvice + @ExceptionHandler
从 Spring 3.2 开始,Spring MVC 引入了 @ControllerAdvice
和 @ExceptionHandler
注解,提供了一种基于注解的异常处理机制。这种方式允许开发者将异常处理逻辑与具体的 Controller 分离,从而实现更加模块化和可重用的异常处理代码。
实现方式:首先,使用 @ControllerAdvice
注解标记一个类,该类将作为全局的异常处理类。然后,在该类中使用 @ExceptionHandler
注解标记方法,并指定该方法用于处理哪种类型的异常。当指定的异常发生时,Spring MVC 将自动调用该方法进行处理
什么是 Spring MVC 的 REST 支持
Spring MVC 的 REST 支持是指其对 RESTful API 的强大集成能力,允许开发者轻松构建符合 REST 架构风格的 Web 服务。通过简洁的注解和丰富的工具,Spring MVC 使控制器能够直接返回 JSON、XML 等数据格式,而非传统的视图页面,从而满足现代前后端分离架构的需求。
一、核心特性与优势
-
注解驱动开发
通过@RestController
、@RequestMapping
等注解快速定义 REST 接口,无需额外配置。 -
自动数据转换
借助HttpMessageConverter
,自动将 Java 对象转换为 JSON/XML 响应,或将请求中的 JSON/XML 反序列化为 Java 对象。 -
统一异常处理
通过@ExceptionHandler
和@ControllerAdvice
统一处理 REST API 的异常,返回标准化错误格式。 -
灵活的请求映射
支持@GetMapping
、@PostMapping
等简化注解,精确匹配 HTTP 方法。 -
内容协商
根据客户端请求的Accept
头或 URL 后缀(如.json
),动态返回不同格式的数据。
如何在 Spring MVC 中处理 JSON 数据
接收 JSON 数据
- 使用
@RequestBody
注解:在控制器方法的参数上使用@RequestBody
注解可以将 HTTP 请求体中的 JSON 数据自动解析为对应的 Java 对象。 - 手动解析 JSON:如果你需要更多的控制权,可以使用 Jackson 或 Gson 等库手动解析 JSON 数据。
返回 JSON 数据
- 使用
@ResponseBody
注解:在控制器方法上使用@ResponseBody
注解可以将方法返回的对象自动序列化为 JSON 数据并写入到 HTTP 响应体中。 - 手动序列化 JSON:如果你需要更多的控制权,可以使用 Jackson 或 Gson 等库手动将 Java 对象序列化为 JSON 数据。
什么是@RestController注解
@RestController
是 用于标记一个类作为 RESTful 控制器。这个注解实际上是 @Controller
和 @ResponseBody
注解的组合。
@ResponseBody将方法返回的对象自动序列化为JSON数据并写入到HTTP响应体中。@Controller则用于标记一个类作为控制器负责处理HTTP请求并将结果返回给客户端
如何在 Spring MVC 中实现跨域资源共享(CORS)
一、全局配置(推荐)
通过实现 WebMvcConfigurer
接口,添加全局 CORS 配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**") // 匹配所有以 /api/ 开头的请求.allowedOrigins("http://example.com") // 允许的域名.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的 HTTP 方法.allowedHeaders("*") // 允许的请求头.allowCredentials(true) // 允许携带凭证(如 Cookie).maxAge(3600); // 预检请求的缓存时间(秒)}
}
二、控制器级别配置
使用 @CrossOrigin
注解在控制器类上:
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://example.com", maxAge = 3600)
public class UserController {// 所有方法都允许来自 http://example.com 的跨域请求
}
三、方法级别配置
在特定方法上使用 @CrossOrigin
注解:
@RestController
@RequestMapping("/api")
public class UserController {@GetMapping("/users/{id}")@CrossOrigin(origins = "http://example.com")public User getUser(@PathVariable Long id) {// 仅该方法允许跨域}
}
如何在 Spring MVC 中使@ExceptionHandler 注解
在 Spring MVC 中,@ExceptionHandler
注解用于处理控制器层抛出的异常,使你可以在同一个控制器或全局范围内定义统一的异常处理逻辑。
一、基本用法:在控制器内处理特定异常
在控制器类中定义异常处理方法,捕获并处理该控制器抛出的特定异常:
@RestController
@RequestMapping("/api/users")
public class UserController {@GetMapping("/{id}")public User getUser(@PathVariable Long id) {User user = userService.findById(id);if (user == null) {throw new UserNotFoundException("用户不存在,ID: " + id);}return user;}// 处理 UserNotFoundException 异常@ExceptionHandler(UserNotFoundException.class)public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {ErrorResponse error = new ErrorResponse(HttpStatus.NOT_FOUND.value(),ex.getMessage());return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);}
}
关键点:
- 异常类型匹配:
@ExceptionHandler
后的括号内指定要捕获的异常类。 - 返回值:可以是
ResponseEntity
、ModelAndView
或其他对象(自动转换为 JSON/XML)。 - 参数:可接收异常对象(如
UserNotFoundException ex
)和请求 / 响应对象。
二、全局异常处理:使用 @ControllerAdvice
创建全局异常处理器,处理所有控制器抛出的异常:
@ControllerAdvice
public class GlobalExceptionHandler {// 处理所有 RuntimeException 及其子类@ExceptionHandler(RuntimeException.class)public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {ErrorResponse error = new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(),"系统内部错误: " + ex.getMessage());return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);}// 处理参数校验异常@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {Map<String, String> errors = ex.getBindingResult().getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));ErrorResponse error = new ErrorResponse(HttpStatus.BAD_REQUEST.value(),"参数校验失败",errors);return ResponseEntity.badRequest().body(error);}
}
关键点:
- @ControllerAdvice:标记该类为全局异常处理器,可通过
basePackages
指定扫描范围。 - 异常优先级:多个
@ExceptionHandler
存在时,优先匹配最具体的异常类(如子类优先于父类)。