Spring MVC设计与实现

DispatcherServlet的初始化与请求处理流程

初始化阶段
  • Servlet 生命周期触发 :当 Web 容器(如 Tomcat)启动时,根据注解/配置,DispatcherServlet 的 init() 方法被调用。

  • 初始化 WebApplicationContext

    • 根 WebApplicationContext :由 ContextLoaderListener 加载,包含 Service、DAO 等非 Web 层 Bean。
    • DispatcherServlet 子上下文:专属于 Servlet,包含 Controller、ViewResolver 等 Web 层 Bean,继承根上下文。
  • 初始化策略组件

    • HandlerMapping :将请求映射到处理器(Controller 方法),如 RequestMappingHandlerMapping
    • HandlerAdapter :执行处理器方法,适配不同处理器类型,如 RequestMappingHandlerAdapter
    • HandlerExceptionResolver:处理请求过程中抛出的异常。
    • ViewResolver:解析逻辑视图名到具体视图(如 JSP、Thymeleaf)。
    • LocaleResolver:解析客户端区域信息(国际化)。
    • ThemeResolver:解析主题信息。
    • RequestToViewNameTranslator:请求到视图名的默认转换。
    • FlashMapManager:管理 Flash 属性(重定向时的临时数据存储)。
    • MultipartResolver:处理文件上传请求。
  • 默认组件加载规则

    • 按类型查找 :从容器中查找对应类型的 Bean(如 ViewResolver)。
    • 默认策略 :若未找到,加载 DispatcherServlet.properties 中定义的默认实现类。
请求处理阶段
  • 请求到达与分发 :当 HTTP 请求到达时,Servlet 容器的 service() 方法触发,最终调用

  • 获取处理器执行链(HandlerExecutionChain)

    • HandlerMapping的作用 :根据请求 URL 匹配对应处理器(Controller方法),并收集关联拦截器(HandlerInterceptor)。
    • 匹配优先级RequestMappingHandlerMapping(基于 @RequestMapping)优先于 BeanNameUrlHandlerMapping
  • 获取处理器适配器(HandlerAdapter)

    • 适配器模式 :不同处理器(如基于注解的 @Controller、传统的 Controller 接口)需要不同的适配器执行。

    • 常用适配器

      RequestMappingHandlerAdapter:处理 @RequestMapping 方法。

      HttpRequestHandlerAdapter:处理 HttpRequestHandler(如静态资源处理)。

      SimpleControllerHandlerAdapter:处理 Controller 接口实现类。

  • 执行处理器方法

    • 参数解析与绑定HandlerMethodArgumentResolver 解析方法参数(如 @RequestParam@RequestBody)。
    • 返回值处理HandlerMethodReturnValueHandler 处理返回值(如 @ResponseBody 转 JSON)。
  • 视图渲染

    • ViewResolver :解析视图名(如 "home")为 View 对象(如 InternalResourceView)。
    • View :渲染模型数据(如填充 JSP 中的 ${message})。
  • 异常处理

    • HandlerExceptionResolver :捕获处理器方法或拦截器抛出的异常,生成错误视图或状态码(如 @ExceptionHandler)。
    • 默认实现ExceptionHandlerExceptionResolver(处理 @ExceptionHandler 方法)、ResponseStatusExceptionResolver(处理 @ResponseStatus 注解)。
  • 拦截器(Interceptor)的执行顺序

    • preHandle():请求处理前执行(如权限校验)。
    • postHandle():处理器方法执行后,视图渲染前执行(如修改模型数据)。
    • afterCompletion():整个请求完成后执行(如资源清理)。

HandlerMapping与HandlerAdapter的职责解析

HandlerMapping:请求与处理器的映射器
  • 核心职责

    • 请求路由:根据HTTP请求的URL、请求方法(GET/POST等)、请求头等信息,找到对应的处理器(Handler)。

    • 处理器链构建 :返回一个HandlerExecutionChain对象,包含目标处理器及其关联的拦截器(HandlerInterceptor)。

    • 多策略支持:支持不同类型的映射策略(如基于注解、基于XML配置、基于Bean名称等)。

  • 常见实现类

    • RequestMappingHandlerMapping :处理@RequestMapping注解(包括@GetMapping@PostMapping等衍生注解)。
    • BeanNameUrlHandlerMapping :根据Bean名称与URL匹配(如Bean名以/开头)。
    • SimpleUrlHandlerMapping: 通过XML或Java配置显式映射URL到处理器(如静态资源处理)。
  • 工作流程

    • 请求匹配 :遍历所有注册的HandlerMapping,调用其getHandler()方法,直到找到匹配的处理器。
    • 拦截器绑定 :将匹配的处理器与配置的拦截器组合成HandlerExecutionChain
    • 优先级控制 :通过Order注解或实现Ordered接口调整多个HandlerMapping的执行顺序。
HandlerAdapter:处理器的适配执行器
  • 核心职责

    • 处理器适配 :将不同类型的处理器(如@ControllerHttpRequestHandler)统一适配为可执行的逻辑。

    • 方法调用:反射调用处理器方法,处理参数绑定、返回值转换等细节。

    • 异常处理:捕获处理器执行过程中的异常,转换为统一的处理流程。

  • 常见实现类

    • RequestMappingHandlerAdapter :适配基于@RequestMapping的处理器方法(最常用)。
    • HttpRequestHandlerAdapter :适配HttpRequestHandler接口(如处理静态资源的ResourceHttpRequestHandler)。
    • SimpleControllerHandlerAdapter :适配实现Controller接口的传统处理器。
  • 工作流程

    • 适配器选择 :根据处理器类型选择对应的HandlerAdapter
    • 参数解析 :通过HandlerMethodArgumentResolver解析请求参数(如@RequestParam@RequestBody)。
    • 方法执行:反射调用处理器方法,获取返回值。
    • 返回值处理 :通过HandlerMethodReturnValueHandler处理返回值(如@ResponseBody转JSON)。

视图解析与渲染

ViewResolver(视图解析器)
  • 作用 :将控制器返回的 逻辑视图名 (如 "home")解析为具体的 View 对象
  • 核心方法View resolveViewName(String viewName, Locale locale)
  • 实现类
    • InternalResourceViewResolver:解析 JSP、HTML 等内部资源视图。
    • ThymeleafViewResolver:解析 Thymeleaf 模板。
    • ContentNegotiatingViewResolver :根据请求的媒体类型(如 Accept 头)协商视图。
    • JsonViewResolver :返回 JSON 视图(如结合 @ResponseBody)。
View(视图)
  • 作用 :负责将模型数据(Model)渲染为具体的响应内容(如生成 HTML、写入 JSON)。
  • 核心方法void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
  • 实现类
    • InternalResourceView:渲染 JSP 页面。
    • ThymeleafView:渲染 Thymeleaf 模板。
    • MappingJackson2JsonView:将模型数据转为 JSON 响应。
    • AbstractPdfView:生成 PDF 文件。
视图解析与渲染流程
  • 控制器返回视图名 :控制器方法返回 String 类型的视图名(如 return "home";)或 ModelAndView 对象。
  • DispatcherServlet 委托 ViewResolver 解析DispatcherServlet 遍历所有注册的 ViewResolver,调用 resolveViewName() 方法,直到找到第一个非 nullView 对象。
    • 优先级控制 :通过 Order 注解或实现 Ordered 接口调整 ViewResolver 的执行顺序。
  • View 渲染模型数据 :获取 View 对象后,调用其 render() 方法,将模型数据与响应结合:
  • 响应返回客户端 :最终生成的 HTML、JSON 或其他内容通过 HttpServletResponse 返回客户端。

参数绑定与数据转换

参数绑定
  • 作用:将外部输入(如 HTTP 请求参数、配置文件值)映射到方法参数或对象属性。
  • 场景 :控制器方法通过@RequestParam绑定请求参数;配置文件通过@Value注入属性值;AOP切面中拦截方法参数进行修改验证。
数据转换
  • 作用 :将字符串或其他类型的输入数据转换为目标类型(如 StringDate)。
  • 核心组件
    • Converter<S, T> :通用类型转换接口(如 StringInteger)。
    • Formatter<T> :面向区域(Locale)的格式化接口(如 DateString)。
    • ConversionService:统一管理所有转换器,提供类型转换服务。
Converter 与 Formatter
  • Converter(类型转换器):适用于通用的类型转换逻辑,无需考虑区域(Locale)。
  • Formatter(格式化器):需考虑区域化的格式化(如日期、货币)。
  • 自动生效 :Spring 在参数绑定时自动调用 ConversionService 完成转换。

异常处理机制

核心组件与职责
  • HandlerExceptionResolver:解析异常并生成错误视图或响应,是异常处理的顶层接口。
  • @ExceptionHandler :注解在方法上,标记该方法用于处理特定类型的异常(通常结合 @ControllerAdvice)。
  • @ControllerAdvice:定义全局异常处理类,集中处理多个控制器的异常。
  • DefaultHandlerExceptionResolver:Spring 默认实现,处理标准 Spring MVC 异常。
  • ResponseStatusExceptionResolver :根据 @ResponseStatus 注解设置 HTTP 状态码和错误信息。
  • ExceptionHandlerExceptionResolver :处理 @ExceptionHandler 注解标记的方法,最常用的异常处理器。
异常处理流程
  • 查找匹配的 @ExceptionHandler :在抛出异常的控制器类中查找 @ExceptionHandler 方法;若未找到,在 @ControllerAdvice 全局类中查找。
  • 遍历 HandlerExceptionResolver链 :Spring 内置的解析器按以下顺序尝试处理异常:
    • ExceptionHandlerExceptionResolver :处理 @ExceptionHandler 方法。
    • ResponseStatusExceptionResolver :处理 @ResponseStatus 注解。
    • DefaultHandlerExceptionResolver:处理标准 Spring 异常。
  • 生成错误响应
    • 解析器返回 ModelAndView(如错误页面)或直接修改 HttpServletResponse(如设置状态码)。
    • 若所有解析器均无法处理异常,由 Servlet 容器(如 Tomcat)返回默认错误页(如 500 页面)。
相关推荐
GJCTYU10 分钟前
spring中@Transactional注解和事务的实战理解附代码
数据库·spring boot·后端·spring·oracle·mybatis
艾迪的技术之路20 分钟前
redisson使用lock导致死锁问题
java·后端·面试
今天背单词了吗98038 分钟前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师41 分钟前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构1 小时前
订单初版—2.生单链路中的技术问题说明文档
java
咖啡啡不加糖1 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南1 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
DKPT1 小时前
Java享元模式实现方式与应用场景分析
java·笔记·学习·设计模式·享元模式
ajassi20001 小时前
开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用
linux·开源·c#·mvc·.net