Spring MVC 是 Spring Framework 中基于 Servlet 的 Web 框架。其前端控制器 DispatcherServlet 协调请求映射、参数解析、控制器调用、返回值处理和异常转换。Spring WebFlux 使用不同的响应式运行时和线程模型;不能将两个框架视为可互换。
引导和分派 #
非 Boot Servlet 应用程序可以通过 WebApplicationInitializer 注册 Web 应用程序上下文和分派器:
public final class WebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
var context = new AnnotationConfigWebApplicationContext();
context.register(WebConfiguration.class);
var servlet = servletContext.addServlet(
"mvc", new DispatcherServlet(context));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}Spring Boot 会为 MVC 应用程序执行等效注册。将分派器映射到 /,可以让 Servlet 容器保留对静态资源和 JSP 的特殊处理;/* 还会捕获这些分派。
对于每个请求,分派器会:
- 向有序的
HandlerMapping实现请求处理器和拦截器; - 选择能够调用该处理器的
HandlerAdapter; - 调用前置处理拦截器和处理器;
- 将返回值作为响应体、视图、异步结果或其他受支持形式进行处理;然后
- 运行异常解析器和完成拦截器。
MVC 策略对象是分派器上下文中的 Bean。@EnableWebMvc 为普通 Spring 应用程序导入标准配置。在 Spring Boot 中,应实现 WebMvcConfigurer 来扩展 Boot 配置,而不是添加 @EnableWebMvc,后者会完全接管自动配置。
请求映射、绑定和验证 #
带注解的控制器可以按路径、HTTP 方法、参数、标头、消耗的媒体类型和生成的媒体类型映射:
@PostMapping(
path = "/orders",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<OrderView> create(@Valid @RequestBody CreateOrder request) {
return ResponseEntity.status(HttpStatus.CREATED)
.body(orderService.create(request));
}HandlerMethodArgumentResolver 实现提供路径变量、查询参数、标头、Cookie、主体、Servlet 对象、模型属性和请求体。简单文本值使用转换和格式化。@ModelAttribute 通过 WebDataBinder 绑定命名属性;应定义允许字段或使用专用命令类型,因为绑定是输入安全边界。@RequestBody 则将媒体解码委托给 HttpMessageConverter。
@Valid 应用 Jakarta Bean Validation,而 @Validated 还可以选择验证组。对于模型属性绑定,紧跟在已绑定参数之后的 BindingResult 参数允许控制器检查转换和验证错误。没有本地处理时,MVC 会通过其异常解析链转换验证异常。
返回值和内容协商 #
HandlerMethodReturnValueHandler 实现处理 ModelAndView、视图名称、ResponseEntity、ProblemDetail 和带有 @ResponseBody 注解的对象等值。响应体值由 HttpMessageConverter 编码。
内容协商会比较处理器的 produces 条件、请求可接受的媒体类型和转换器能力。不支持的 Content-Type 请求会产生 415;没有可接受的响应表示会产生 406。优先使用 Accept 标头和显式默认值,而不是路径扩展协商。
异常解析 #
HandlerExceptionResolver 将失败转换为模型、状态或响应。标准注解配置包括:
ExceptionHandlerExceptionResolver,用于控制器和@ControllerAdvice异常方法;ResponseStatusExceptionResolver,用于@ResponseStatus和ResponseStatusException;以及DefaultHandlerExceptionResolver,用于框架异常。
集中式建议应将领域失败映射为稳定的状态码和一致的错误模式。Spring Framework 6 引入了 ProblemDetail 和 ErrorResponse;Spring 6.1 文档根据 RFC 9457 描述其问题详情支持,该 RFC 已取代 RFC 7807。
线程、异步请求和上下文 #
同步 MVC 处理运行在 Servlet 容器线程上。阻塞的数据库或 HTTP 调用会在完成前一直占用该线程,因此应从连接器到每个下游依赖配置截止时间和容量。
控制器可以返回 Callable、DeferredResult 或 WebAsyncTask。MVC 启动 Servlet 异步处理,释放容器线程,并在结果就绪时执行后续 ASYNC 分派。异步 MVC 不会使阻塞代码变为非阻塞;它只是将工作移动到另一个执行器。应明确配置该执行器、超时、取消和过载行为。
线程局部的日志、区域设置、安全和观测状态不会自动跟随任意执行器任务。使用受支持的拦截器或任务装饰器,或显式传递上下文,并始终清除恢复的状态。
评论
在 GitHub 上阅读或评论(发表评论需要登录)