目录
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是Spring框架中的一个模块用于构建基于Web的应用程序。遵循Model-View-Controller的设计模式,将业务逻辑、用户界面和数据分离。
处理流程
核心组件
DispatcherServlet
是 SpringMVC 框架的核心组件,作为整个请求处理流程的中央调度器(Front Controller),负责接收所有 HTTP 请求并协调各个组件完成请求的处理和响应。
1.统一入口
所有请求(如 /user/list
、/order/create
)都由 DispatcherServlet
接收,避免每个控制器单独处理 HTTP 连接。
2.职责分离
DispatcherServlet
不处理具体业务逻辑,仅负责:
3.遵循 MVC 模式
将请求处理、业务逻辑和视图渲染分离,提高代码可维护性。
当客户端发送请求时,DispatcherServlet
的处理流程如下:
DispatcherServlet
。HandlerMapping
找到处理该请求的控制器方法(Handler)。HandlerAdapter
调用控制器方法。ModelAndView
。ViewResolver
将逻辑视图名解析为具体视图(如 JSP、JSON)。HandlerMapping
是 SpringMVC 框架中的核心组件之一,负责将 HTTP 请求映射到对应的处理器(Handler),即控制器(Controller)中的方法。
请求路由
当客户端发送请求(如 GET /user/list
)时,HandlerMapping
需确定由哪个控制器方法处理该请求。
解耦 URL 与处理器
通过配置或注解,将 URL 模式(如 /user/*
)与处理器绑定,无需硬编码映射关系。
支持多种映射策略
可根据路径、请求方法、请求参数等条件进行复杂匹配。
当 DispatcherServlet
接收到请求时,HandlerMapping
的工作流程如下:
UserController.listUsers()
方法)。SpringMVC 提供多种 HandlerMapping
实现,支持不同的映射方式:
1. RequestMappingHandlerMapping(最常用)
@RequestMapping
、@GetMapping
、@PostMapping
等注解。/user/{id}
)?action=edit
)Content-Type
)2. SimpleUrlHandlerMapping
3. BeanNameUrlHandlerMapping
/
开头的 Bean。/userController
,则映射到 /userController
路径。HandlerAdapter
是 SpringMVC 框架中的核心组件之一,负责 ** 调用具体的处理器(Handler)** 并处理其返回值。由于 SpringMVC 支持多种处理器类型(如注解方法、实现 Controller
接口的类),HandlerAdapter
的作用是将不同类型的处理器统一适配为可执行的标准接口。
统一调用接口
不同类型的处理器(如 @RequestMapping
注解的方法、实现 Controller
接口的类)具有不同的调用方式。HandlerAdapter
将它们统一为 handle()
方法,使 DispatcherServlet
无需关心具体调用细节。
解耦处理器类型
处理器的实现方式(如注解驱动、接口驱动)可以灵活变化,只需提供对应的 HandlerAdapter
实现即可。
参数解析与返回值处理
负责解析 HTTP 请求参数到处理器方法参数,并将处理器返回值转换为 ModelAndView
或其他响应格式。
当 DispatcherServlet
通过 HandlerMapping
找到匹配的处理器后,HandlerAdapter
的工作流程如下:
DispatcherServlet
调用 supports()
方法,确认当前 HandlerAdapter
是否支持该处理器类型。handle()
方法,执行处理器逻辑并返回 ModelAndView
。String
、User
对象)转换为 ModelAndView
或直接写入响应。在 SpringMVC 中,View Resolver(视图解析器) 是负责将控制器返回的逻辑视图名(如 "user/list"
)解析为实际视图对象(如 JSP、Thymeleaf 模板或 JSON 转换器)的组件。它是连接控制器逻辑和视图渲染的桥梁,使控制器无需关心具体的视图实现细节。
解耦视图实现
控制器只需返回逻辑视图名(如 "success"
),无需指定具体的视图技术(如 JSP、Thymeleaf),实现了业务逻辑与视图渲染的分离。
统一视图处理流程
DispatcherServlet 通过 View Resolver 统一处理所有视图,简化了请求处理流程。
支持多种视图技术
同一应用中可同时使用不同的视图技术(如 JSP、Freemarker、JSON),通过不同的 View Resolver 实现切换。
当控制器返回 ModelAndView
时,View Resolver 的工作流程如下:
ModelAndView
中提取逻辑视图名(如 "user/list"
)。JstlView
、ThymeleafView
)。render()
方法,将模型数据填充到视图模板中,并输出响应。ModelAndView
用于封装模型数据和视图信息。它允许控制器方法返回一个对象,该对象包含视图名称和模型数据,从而将数据传递给视图进行渲染。
ModelAndView
主要解决两个问题:
其本质是一个容器,包含两个关键部分:
ModelAndView
的优点ModelAndView
对象,可以避免在控制器方法中显式设置模型和视图。@ModelAttribute
注解是 Spring MVC 中用于绑定请求参数到模型对象的注解。它可以用于方法参数、方法和控制器类中,以便将请求中的数据绑定到模型对象,并将该对象添加到模型中,以便在视图中使用。
@ModelAttribute
的使用场景@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
注解是 Spring MVC 中用于将 URL 路径中的变量绑定到处理方法的参数上的注解。它允许你从 URL 路径中提取参数,并将这些参数传递给控制器方法,从而实现更加动态和灵活的 URL 路由。
在 Spring MVC 中,拦截器(Interceptor) 是一种特殊的组件,用于在请求处理的关键节点插入自定义逻辑。它类似于 Servlet 规范中的 Filter,但功能更强大、更灵活,是 AOP(面向切面编程)思想的典型应用。
拦截器允许开发者在不修改控制器代码的前提下,对请求进行全局或局部的增强处理。
当客户端发送请求时,拦截器的执行流程如下:
preHandle
方法。若任一拦截器返回 false
,则终止请求处理,直接返回响应。preHandle
均返回 true
时执行。postHandle
,可修改 ModelAndView
。Spring MVC 的拦截器通过实现 HandlerInterceptor
接口来定义。这个接口包含三个主要方法:
preHandle
:在请求处理之前执行。返回 true
表示继续处理请求,返回 false
表示中止请求。postHandle
:在请求处理之后、视图渲染之前执行。可以修改视图模型数据。afterCompletion
:在整个请求完成之后(包括视图渲染之后)执行。通常用于资源清理。在 Spring MVC 中,异常处理机制用于统一捕获和处理控制器层抛出的异常,避免直接将异常堆栈暴露给客户端,同时提供友好的错误响应。
从 Spring 3.2 开始,Spring MVC 引入了 @ControllerAdvice
和 @ExceptionHandler
注解,提供了一种基于注解的异常处理机制。这种方式允许开发者将异常处理逻辑与具体的 Controller 分离,从而实现更加模块化和可重用的异常处理代码。
实现方式:首先,使用 @ControllerAdvice
注解标记一个类,该类将作为全局的异常处理类。然后,在该类中使用 @ExceptionHandler
注解标记方法,并指定该方法用于处理哪种类型的异常。当指定的异常发生时,Spring MVC 将自动调用该方法进行处理
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
),动态返回不同格式的数据。
@RequestBody
注解:在控制器方法的参数上使用 @RequestBody
注解可以将 HTTP 请求体中的 JSON 数据自动解析为对应的 Java 对象。@ResponseBody
注解:在控制器方法上使用 @ResponseBody
注解可以将方法返回的对象自动序列化为 JSON 数据并写入到 HTTP 响应体中。@RestController
是 用于标记一个类作为 RESTful 控制器。这个注解实际上是 @Controller
和 @ResponseBody
注解的组合。
@ResponseBody将方法返回的对象自动序列化为JSON数据并写入到HTTP响应体中。@Controller则用于标记一个类作为控制器负责处理HTTP请求并将结果返回给客户端
通过实现 WebMvcConfigurer
接口,添加全局 CORS 配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public 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
注解用于处理控制器层抛出的异常,使你可以在同一个控制器或全局范围内定义统一的异常处理逻辑。
在控制器类中定义异常处理方法,捕获并处理该控制器抛出的特定异常:
@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 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
public class GlobalExceptionHandler {
// 处理所有 RuntimeException 及其子类
@ExceptionHandler(RuntimeException.class)
public ResponseEntity 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 handleValidationException(MethodArgumentNotValidException ex) {
Map 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);
}
}
关键点:
basePackages
指定扫描范围。@ExceptionHandler
存在时,优先匹配最具体的异常类(如子类优先于父类)。