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 页面)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/904601.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/904601.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

64.微服务保姆教程 (七) RocketMQ--分布式消息中间件

RocketMQ–分布式消息中间件 一、MQ 1、什么是MQ MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据结构。指把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队…

java算法的核心思想及考察的解题思路

一、Java算法的核心思想 1. 分而治之 (Divide and Conquer) 将大问题分解为小问题&#xff0c;递归解决小问题后合并结果 典型应用&#xff1a;归并排序、快速排序、二分查找 2. 动态规划 (Dynamic Programming) 将问题分解为重叠子问题&#xff0c;存储子问题的解避免重复…

linux查java进程CPU高的原因

问题&#xff1a;linux查java进程CPU高的原因 解决&#xff1a;用jdk带的工具分析 被查的java最好也使用jdk启动 systemctl启动的注意要去掉PrivateTmptrue /opt/jdk1.8.0_441/bin/jps -l top -Hp 8156 printf "%x" 8533 /opt/jdk1.8.0_441/bin/jstack 8156 |…

体育培训的实验室管理痛点 质检LIMS如何重构体育检测价值链

在竞技体育与全民健身并行的时代背景下&#xff0c;体育培训机构正面临双重挑战&#xff1a;既要通过科学训练提升学员竞技水平&#xff0c;又需严格把控运动安全风险。作为实验室数字化管理的核心工具&#xff0c;质检LIMS系统凭借其标准化流程管控与智能化数据分析能力&#…

linux下MySql的安装与配置

一键三联&#xff0c;把mysql的安装与配置也写了&#xff0c;供各位参考。 --------------------------------------MySql的安装与配置-------------------------------------- 1 将下载的 压缩包解压到指定目录 tar -zxvf mysql-5.7.26-linux-glibc2.12-x86_64.tar.gz 卸载…

数据库原理与应用实验二 题目七

利用sql建立教材数据库,并定义以下基本表: 学生(学号,年龄,性别,系名) 教材(编号,书名,出版社编号,价格) 订购(学号,书号,数量) 出版社(编号,名称,地址) 1定义主码、外码、和价格、数量的取值范围。 2 在三个表中输入若干记录,注意如果输入违反完整…

什么是 HSQLDB?

大家好&#xff0c;这里是架构资源栈&#xff01;点击上方关注&#xff0c;添加“星标”&#xff0c;一起学习大厂前沿架构&#xff01; Java开发人员学习Java数据库连接&#xff08;JDBC&#xff09;的最简单方法是试验HyperSQL数据库&#xff08;又名HSQLDB&#xff09;。 …

shell脚本--2

1、实时监控cpu、内存的shell脚本 #!/bin/bash# 获取当前时间 DATE$(date "%Y-%m-%d %H:%M:%S")# 获取CPU使用情况 CPU_USAGE$(top -b -n1 | grep "Cpu(s)" | awk {print $2 $4})# 获取内存使用情况 MEMORY_USAGE$(free | grep Mem | awk {print $3/$2 *…

性能比拼: HTTP/2 vs. HTTP/3

本内容是对知名性能评测博主 Anton Putra HTTP/2 vs. HTTP/3 performance benchmark 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准 在本内容中&#xff0c;我们将比较 HTTP/2 和 HTTP/3 协议。 我们将使用 Terraform 和 Ansible 在 Google Cloud Platform (GCP) …

【Vue】组件自定义事件 TodoList 自定义事件数据传输

目录 一、绑定 二、解绑 组件自定义事件总结 TodoList案例对数据传输事件的修改 总结不易~ 本章节对我有很大收获&#xff0c; 希望对你也是&#xff01;&#xff01;&#xff01; 本章节素材已上传Gitee&#xff1a;yihaohhh/我爱Vue - Gitee.com 前面我们学习的clikc、…

Windows远程连接MySQL报错,本地navicat能连接MySQL

一、报错 telnet 119.87.111.79 3306​​“无法打开到主机的连接。在端口 3306: 连接失败”​​ 表明无法通过 TCP 协议连接到目标服务器的 3306 端口。 二、目的 &#xff08;1&#xff09;​​Telnet 测试的目的​​ Telnet 仅用于测试 ​​TCP 端口是否开放​​&#xff…

电池管理系统BMS三级架构——BMU、BCU和BAU详解

储能电站的电池管理系统&#xff08;BMS&#xff09;通常采用三级架构&#xff1a;从控&#xff08;BMU&#xff09;、主控&#xff08;BCU&#xff09;、总控&#xff08;BAU&#xff09;。这种分层设计实现了电池模组、簇、堆的分级管理和控制&#xff0c;确保系统运行的安全…

C++ 基础复习

基础复习 1.const引用为什么能引用临时对象2.内联函数的额外作用3. nullptr 1.const引用为什么能引用临时对象 临时对象&#xff08;Temporary Object&#xff09;是在表达式求值过程中隐式创建的对象&#xff0c;例如&#xff1a; 函数返回非引用类型的值 类型转换&#xff0…

AI的出现,是否能替代IT从业者?

阐述观点&#xff1a;AI 的出现不会完全替代 IT 从业者&#xff0c;但会深刻改变 IT 行业的工作方式和岗位结构。 AI 不会完全替代 IT 从业者的原因 AI 本身需要人来开发与维护 AI 模型、系统架构、数据管道等都需要 IT 专业人员来构建和优化。 例如&#xff1a;AI 工程师、M…

【服务器通信-socket】——int socket(int domain, int type, int protocol);

#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol); domain: AF_INET 这是大多数用来产生socket的协议&#xff0c;使用TCP或UDP来传输&#xff0c;用IPv4的地址 AF_INET6 与上面类似&#xff0c;不过是来用IPv6的地…

Python基本环境搭配

Python3 环境搭建 | 菜鸟教程 里面有直接跳转 Fitten Code 按下 Tab 键接受所有补全建议&#xff1a; 按下 Ctrl→ 键(mac系统为Command→)接收单个词补全建议&#xff1a; 用户可通过点击左上角工具栏中的Fitten Code – 开始对话或者使用快捷键CtrlAltC(mac系统为Contr…

C++负载均衡远程调用学习之HOOK注册机制

目录 1.larV0.7-hook流程的说明 2.larV0.7-TCP_server集成链接HOOK函数 3.larV0.7-TCP_client集成链接HOOK注册功能 1.larV0.7-hook流程的说明 ### 7.1 数据库表相关查询方法实现 ​ 我们先实现一些基本的数据表达查询方法&#xff1a; > lars_dns/src/dns_rout…

Rust 与 Golang 深度对决:从语法到应用场景的全方位解析

一、引言 在软件开发的快速发展浪潮中&#xff0c;Rust 和 Golang&#xff08;Go 语言&#xff09;脱颖而出&#xff0c;成为开发者热议的编程语言。Rust 凭借强大的内存安全性与卓越的性能备受赞誉&#xff0c;Golang 则以简洁的语法和出色的并发处理能力赢得开发者青睐。本文…

C++负载均衡远程调用学习之订阅功能与发布功能

目录 1.lars-DnsV0.1回顾 2.Lars-DnsV0.2-订阅功能的订阅模块分析 3.Lars-DnsV0.2-订阅模块的类的单例创建及方法属性初始化 4.Lars-DnsV0.2-发布功能的实现 5.Lars-DnsV0.2-发布功能的总结 6.Lars-DnsV0.2-订阅流程复习 7.Lars-DnsV0.2-订阅模块的集成 8.Lars-DnsV0.2订…

SurfSense开源程序是NotebookLM / Perplexity / Glean的开源替代品,连接到外部来源,如搜索引擎

​一、软件介绍 文末提供程序和源码下载 虽然 NotebookLM 和 Perplexity 等工具令人印象深刻&#xff0c;并且对于对任何主题/查询进行研究都非常有效&#xff0c;但 SurfSense 通过与你的个人知识库集成来提升这种能力。它是一个高度可定制的 AI 研究代理&#xff0c;连接到外…