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 页面)。
#java##Spring#
全部评论

相关推荐

04-24 22:52
已编辑
黑龙江大学 golang
首先,公司说话全程春秋笔法,掐头去尾捏造事实,希望各位网友理性看待。自我介绍一下,我是本次被公司曝光的离职员工之一,针对公司发表的“小作文”中的一些话,我打算曝光一下事实。我自21年初入职,工作至24年10月中旬,被公司人力葳鞋主动离职,原因是认为我产出较低,让我主动离职,否则:黑我背调、葳鞋让我缴纳入职以来食堂5万元餐补、官网曝光我的个人信息、追踪我下家入职公司去搞我、葳鞋找我父母麻烦(均有证据)。我争论说我去年绩效评分3.5是正常的,实在不行希望可以调岗或者降薪,都能接受,但最终仍然改变不了结果。公司人力是分别约去谈话,去谈话时,会要求我们将手机、手表关机并放到桌上,会让我们把口袋外翻,并用金属探测仪搜身,避免员工录音获取证据。但当时我和其他同事还是成功录到了每一次谈话的录音(包括老板亲自下场和我的“单方面”谈话内容)公司微博的“小作文”看看就得了,想阐述的核心观点无非就是“仲裁员裁决不公平,公司没有提供劳动条件,仲裁员怎么能让企业强制员工加班呢?我要用我坚实的春秋笔法,激起舆论,让更多同道中人为我站台!”等等。关于“公司没有提供劳动条件”这部分,我详细解释说明一下:●针对公司说的“下班期间关闭电脑是公司的正常管理行为”这个言论,实际情况是:即使在公司表面要求的工作时间内,即9:00-18:00,我和其他几位组内的被葳鞋主动离职的同事,都经常遇到工作电脑被远程自动关机并且无法开机的情况(重启十几次)。然而除了被葳鞋主动离职的同事,其他同事都没有这个情况。我工作的三年多以来,也从未发生过如此的情况。并且,IT同事来修电脑的时候,也承认了公司对我的电脑做了一些手脚。上述内容,我均已录像。●针对公司说的“公司也足额发放工资”这个言论,实际情况是:公司恶意拆分工资结构,基本工资仅占1/3,晚上两小时的加班时间的工资占比为2/3,本人的岗位薪资为固定工资,通过个税app以及银行流水可查,且已提交给仲裁委。公司在葳鞋员工主动离职后,会故意到18点时,远程关闭本人及其他几位被葳鞋主动离职的同事的电脑,让我们无法继续工作,然后故意歪曲事实,杜撰出“仲裁员让企业强制员工加班”,将脏水泼到仲裁员身上。●针对公司说的“公司当然有经常安排员工加班,也配发了加班费。”这个言论,实际情况是:部门内几乎所有员工都是正常的996,并且公司从未发放过工资条,只允许内网上查看上月薪资,这几年甚至先后两次改动了工资结构,越改越复杂。在未重新签署劳动合同的情况下,就私自单方面的重新修改工资结构。2024年的工资结构已经改成了:基本工资、加班费及值班补贴、学习补贴、全勤奖、其他补贴等。公司所说的“加班费”,实际上就是员工入职时谈好的月薪,并且年终奖也是按月薪比例发放的。公司在此实际上就是故意拆分工资结构以掩盖违法目的,仲裁委和法院是不可能会认可的!●我和其他同事被葳鞋主动离职后,工作权限都是被马上收回,无法看到部门内部文档和代码,此后组长就被要求让我停止之前的工作,去做其它业务,期间我请求恢复工作权限,但组长仍然禁止我浏览公司内的任何文档和代码,故意增大工作难度。(有聊天记录证据)●公司大部分部门的员工(技术岗),都是要求晚上21点下班(以前经常晚上十点多才下班),并不是所谓的18点。这是公司要求的制度,员工都在公司正常工作(但晚上的工作时间被老板美名其曰为“免费学习时间”)。公司居然能“问心无愧”的说出如此违背事实的内容!甚至说“仲裁员要求企业逼迫员工加班”这种话,此等无稽之谈,可谓毫无下限可言。公司发布的这篇“小作文”,表面想阐述的是“公司已提供必要的劳动条件,并且认为仲裁委裁判不公”,核心目的实则是引导广大网友和企业认为“仲裁委不公,企业必须安排员工加班”等谬论,故意扭曲事实,激起舆论,恶化劳资关系。我不知道有多少网友会认为公司说的这些内容是事实,仅希望各位网友辩证看待。我这边有人力、老板和我沟通的每一次对话的录音,录音中有下述内容(后续整理,看看情况是否曝光): ●人力:如果不主动离职,以后背调可能...,还有需要补交一下入职以来的餐费,每餐30(总共将近5万)●人力:已经确定了,如果你主动离职,就不会起诉你退还餐费●人力:签不签?&nbsp;我回复:不签&nbsp;人力:那好好工作,后面会通过火星(公司内部通讯软件)发给你(餐费催缴)通知书●老板:(暂时隐藏1)●老板:(暂时隐藏2)●老板:(暂时隐藏3)●等等...如果公司真的把我逼的无路可走,故意让我后续因为背调找不到工作,或者追踪我下家入职公司说我坏话,亦或者真的去搞我父母的工作的话。我在这儿能说的,可能也只有说整理证据并且视频曝光这件事情始末。反正都被开盒了,如果因此以后找不到工作了,那也没什么可以怕了。😁ps1:本篇已做脱敏处理,未出现公司名称、人名等信息,希望平台不要因为收到举报就直接和谐我的文章,感谢平台!感谢各位!ps2:抱歉了,各位还在公司的同事们,公司经过我和其他几位同事的仲裁,后续日常检查员工手机以及进会议室金属探测仪搜身的力度应该会大很多,想要获取证据应该非常难了!望各位珍重!(尤其是每年底裁员的时候)😭😭😭
真烦好烦真烦:吓人,打工人真不容易
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务