当前位置: 首页 > news >正文

Spring MVC 九大组件源码深度剖析(五):HandlerAdapter - 处理器的执行引擎

文章目录

    • 一、HandlerAdapter的战略地位
    • 二、核心接口设计
    • 三、四大实现类源码解析
      • 1. SimpleControllerHandlerAdapter(传统Controller接口)
      • 2. HttpRequestHandlerAdapter(静态资源处理器)
      • 3. SimpleServletHandlerAdapter(原生Servlet支持)
      • 4. RequestMappingHandlerAdapter(现代注解控制器核心)
    • 四、RequestMappingHandlerAdapter的三大子系统
      • 1. 参数解析器(HandlerMethodArgumentResolver)
      • 2. 返回值处理器(HandlerMethodReturnValueHandler)
      • 3. 数据绑定器(WebDataBinderFactory)
    • 五、方法执行核心流程
      • 1. 参数解析阶段
      • 2. 方法调用阶段
      • 3. 返回值处理阶段
    • 六、高级特性:异步处理
      • 1. Callable异步执行
      • 2. DeferredResult延迟结果
    • 七、性能优化实践
      • 1. 参数解析器缓存
      • 2. 预编译参数解析
    • 八、设计思想总结
    • 扩展

本文是Spring MVC九大组件解析系列第五篇,我们将深入探索请求处理的核心引擎,揭秘Controller方法如何被调用,解析参数绑定返回值处理的魔法,以及如何支持多样化处理器类型。
Spring MVC整体设计核心解密参阅:Spring MVC设计精粹:源码级架构解析与实践指南

一、HandlerAdapter的战略地位

在Spring MVC架构中,HandlerAdapter扮演着中央处理器的关键角色:

  • 统一接口:为不同类型的处理器提供统一调用方式
  • 执行引擎:驱动Controller方法的实际执行
  • 处理中枢:协调参数解析、方法调用、返回值处理全流程

在这里插入图片描述

二、核心接口设计

源码位置org.springframework.web.servlet.HandlerAdapter
核心源码
截图

设计哲学:通过适配器模式统一多样化处理器的执行接口。

三、四大实现类源码解析

1. SimpleControllerHandlerAdapter(传统Controller接口)

支持对象:实现Controller接口的处理器
源码位置org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
核心源码
截图

经典实现

public class UserController implements Controller {public ModelAndView handleRequest(HttpServletRequest request, ...) {return new ModelAndView("users", "userList", userService.getAll());}
}

2. HttpRequestHandlerAdapter(静态资源处理器)

支持对象:实现HttpRequestHandler的处理器
源码位置org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
核心源码

截图

典型应用ResourceHttpRequestHandler处理静态资源

3. SimpleServletHandlerAdapter(原生Servlet支持)

支持对象:标准Servlet实现
源码位置org.springframework.web.servlet.handler.SimpleServletHandlerAdapter
核心源码
截图

整合价值:无缝集成传统Servlet组件

4. RequestMappingHandlerAdapter(现代注解控制器核心)

支持对象@Controller@RequestMapping注解方法
源码位置org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
核心源码
截图
在这里插入图片描述
在这里插入图片描述

四、RequestMappingHandlerAdapter的三大子系统

1. 参数解析器(HandlerMethodArgumentResolver)

源码位置org.springframework.web.method.support.HandlerMethodArgumentResolver
接口定义
截图

核心实现

解析器类型处理的参数/注解示例说明
RequestParamMethodArgumentResolver@RequestParam(@RequestParam String name) {}解析name参数
PathVariableMethodArgumentResolver@PathVariable(@PathVariable Long id) {}解析路径变量id
RequestHeaderMethodArgumentResolver @RequestHeader(@RequestHeader("Authorization") String token) {}解析请求头Authorization
CookieValueMethodArgumentResolver @CookieValue(@CookieValue("JSESSIONID") String sessionId) {}解析Cookie值
ModelAttributeMethodProcessor @ModelAttribute或POJO对象(@ModelAttribute User user) {}; (User user) {}解析User对象,从请求参数绑定属性;自动绑定请求参数到User对象
RequestResponseBodyMethodProcessor@RequestBody 处理JSON/XML等请求体(@RequestBody User user) {}从请求体中反序列化User对象
ServletRequestMethodArgumentResolverHttpServletRequest(HttpServletRequest request) {}直接注入Servlet API对象
ServletResponseMethodArgumentResolverHttpServletResponse(HttpServletResponse response) {}直接注入Servlet API对象
SessionMethodArgumentResolver@SessionAttribute(@SessionAttribute("user") User sessionUser) {}从Session中获取user属性
PrincipalMethodArgumentResolver解析认证主体(Principal)参数(Principal principal) {}获取当前认证用户信息
RequestAttributeMethodArgumentResolver@RequestAttribute(@RequestAttribute("startTime") Long startTime) {}从request属性中获取值
MapMethodProcessorMap<String, String> 类型参数(Map<String, String> allParams) {}allParams包含所有请求参数
MatrixVariableMethodArgumentResolver矩阵变量(Matrix Variable) (@MatrixVariable Map<String, String> matrixVars) {}解析矩阵变量,如/cars/bmw;color=red;year=2020/models/X5

执行流程
在这里插入图片描述

2. 返回值处理器(HandlerMethodReturnValueHandler)

源码位置org.springframework.web.method.support.HandlerMethodReturnValueHandler
接口定义
在这里插入图片描述

核心实现

返回值处理器类型处理的返回值类型说明
ModelAndViewMethodReturnValueHandlerModelAndView处理返回类型为 ModelAndView 的方法;将返回的 ModelAndView 对象传递给视图解析器渲染视图
ViewMethodReturnValueHandlerView处理直接返回 View 对象的方法;直接使用返回的视图对象进行渲染
ViewNameMethodReturnValueHandler视图名称字符串处理返回字符串类型的方法(视图名称);将字符串解析为视图名进行渲染
RequestResponseBodyMethodProcessor@ResponseBody处理带有 @ResponseBody 注解的方法返回值;将返回对象序列化为JSON/XML等格式写入响应体;是REST API中最常用的处理器
HttpEntityMethodProcessorResponseEntity处理返回 HttpEntity 或 ResponseEntity 类型的方法;允许直接控制HTTP响应头和状态码
StreamingResponseBodyReturnValueHandlerStreamingResponseBody处理返回 StreamingResponseBody 类型的方法;支持流式响应,适用于大文件下载等场景
CallableMethodReturnValueHandlerCallable处理返回 Callable 类型的方法;支持异步处理,将任务提交给线程池执行
DeferredResultMethodReturnValueHandlerDeferredResult处理返回 DeferredResult 类型的方法;支持异步处理,允许手动设置处理结果
AsyncTaskMethodReturnValueHandlerWebAsyncTask处理返回 WebAsyncTask 类型的方法;提供更丰富的异步处理能力,包括超时设置等

3. 数据绑定器(WebDataBinderFactory)

源码位置org.springframework.web.bind.support.WebDataBinderFactory
接口定义
截图

核心实现

绑定器类型说明
DefaultDataBinderFactory最常用的实现类,是其他实现类的基础;创建标准的 WebDataBinder 实例;提供基本的数据绑定和验证功能;支持初始化绑定器的回调方法
InitBinderDataBinderFactory扩展自 DefaultDataBinderFactory;支持处理控制器中的 @InitBinder 方法;允许自定义数据绑定规则和验证器;在创建 WebDataBinder 时会调用相应的 @InitBinder 方法
ServletRequestDataBinderFactory专门用于处理Servlet请求数据绑定;创建 ServletRequestDataBinder 实例;支持从HTTP请求参数中绑定数据到目标对象;处理请求参数、表单数据等的绑定
ExtendedServletRequestDataBinderFactory扩展的Servlet请求数据绑定工厂;支持更复杂的数据绑定场景;处理路径变量、请求头等额外数据源的绑定

核心职责

  • 数据绑定:将请求参数绑定到对象
  • 类型转换:使用ConversionService转换数据类型
  • 数据校验:通过Validator接口执行校验
// 数据绑定示例
public class UserController {@PostMapping("/users")public String createUser(@Valid User user, BindingResult result) {if (result.hasErrors()) {return "error";}// ...}
}

五、方法执行核心流程

1. 参数解析阶段

核心源码org.springframework.web.method.support.InvocableHandlerMethod
在这里插入图片描述
在这里插入图片描述

2. 方法调用阶段

截图

3. 返回值处理阶段

截图
在这里插入图片描述

六、高级特性:异步处理

1. Callable异步执行

@GetMapping("/async")
public Callable<String> asyncProcessing() {return () -> {Thread.sleep(3000); // 模拟耗时操作return "async-result";};
}

实现原理 & 关键源码:RequestMappingHandlerAdapter
截图
在这里插入图片描述
在这里插入图片描述

2. DeferredResult延迟结果


private DeferredResult<String> deferredResult;@GetMapping("/deferred")
public DeferredResult<String> deferredProcessing() {deferredResult = new DeferredResult<>();return deferredResult;
}// 其他线程设置结果
public void setResult(String data) {deferredResult.setResult(data);
}

实现原理 & 关键源码:RequestMappingHandlerAdapter
在这里插入图片描述
在这里插入图片描述

七、性能优化实践

1. 参数解析器缓存

// 优化点:避免每次请求都查找解析器
public class CachedInvocableHandlerMethod extends InvocableHandlerMethod {private HandlerMethodArgumentResolver[] cachedResolvers;private Object[] getMethodArgumentValues(...) {if (cachedResolvers == null) {// 首次解析时缓存解析器cachedResolvers = new HandlerMethodArgumentResolver[parameters.length];for (int i = 0; i < parameters.length; i++) {cachedResolvers[i] = findResolver(parameters[i]);}}// 使用缓存解析器for (int i = 0; i < parameters.length; i++) {args[i] = cachedResolvers[i].resolveArgument(...);}return args;}
}

2. 预编译参数解析

// 启动时预编译参数解析逻辑
@PostConstruct
public void precompileArgumentResolvers() {for (ControllerInfo controller : controllers) {for (Method method : controller.getMethods()) {for (Parameter parameter : method.getParameters()) {// 预热参数解析器argumentResolvers.findResolver(parameter).supportsParameter(parameter);}}}
}

八、设计思想总结

  1. 适配器模式典范
    统一接口支持多样化处理器
  2. 关注点分离
    参数解析/方法执行/返回值处理职责分离
  3. 可扩展架构
    自定义ArgumentResolver和ReturnValueHandler
  4. 异步非阻塞
    无缝整合Servlet 3.0+异步规范
  5. 性能优化导向
    缓存/预编译提升效率

下一篇预告:
九大组件源码剖析(六):HandlerExceptionResolver - 异常处理的艺术
我们将深入分析Spring MVC的异常处理机制,揭秘@ControllerAdvice的实现原理,以及如何构建统一的异常处理体系。


扩展

HandlerAdapter 及其实现类 Diagram
在这里插入图片描述
组合模式(Composite Pattern)
组合模式是一种结构型设计模式,它将对象组合成树形结构以表示"部分-整体"的层次结构,使得客户端可以统一处理单个对象和组合对象。

典型应用
处理方法参数解析:HandlerMethodArgumentResolverComposite.java
处理方法返回值:HandlerMethodReturnValueHandlerComposite.java
处理异常解析:HandlerExceptionResolverComposite.java

组合模式的优势:

  1. 统一接口
    • 客户端代码只需要与Composite接口交互
    • 无需关心内部有多少个具体处理器
  2. 易于扩展
    • 可以轻松添加新的处理器而不需要修改现有代码
    • 符合开闭原则(对扩展开放,对修改关闭)
  3. 灵活的组合
    • 可以在运行时动态组合不同的处理器
    • 支持优先级排序和条件选择

工作流程

  1. 客户端调用Composite处理方法
  2. Composite内部遍历所有处理器,找到支持的处理器
  3. 委托给具体处理器执行
http://www.dtcms.com/a/360502.html

相关文章:

  • 三、环境搭建之Docker安装mysql
  • 一、计算机系统知识
  • Springcloud-----Nacos
  • 【influxdb】InfluxDB 2.x 线性写入详解
  • 层次分析法
  • Redis实现短信登录
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘SQLModel’问题
  • 37. 解数独
  • 解锁Tensor Core性能:深入探索CUDA Warp矩阵操作
  • Dify构建AI应用
  • FART 主动调用组件深度解析:破解 ART 下函数抽取壳的终极武器
  • #Datawhale 组队学习#8月-工作流自动化n8n入门-3
  • 第七章 使用角色和Asible内容集合简化Playbook
  • 4.4 光照(4) - 高光反射
  • 硬件工程师成长之路:从入门到精通的技术旅程
  • [Plecs基础知识系列]建立自定义模块/子系统(Subsystem)
  • C++ 面试高频考点 力扣 69. x 的平方根 二分查找 题解 每日一题
  • Linux网络socket套接字(中)
  • 切片语法[::-1]及其可用的类型
  • 基于单片机智能鞋柜/智能鞋橱/智能鞋盒
  • Linux - #操作系统概念 #权限
  • 获取某天的零点日期
  • Java 异常处理全解析:从基础到实践
  • Rust 登堂 之 枚举和整数(八)
  • OpenCL C++ 平台与设备
  • 集合-单列集合(Collection)
  • DrissionPage 实战:动态 IP 代理与百度翻译 API 数据抓取
  • LeetCode算法日记 - Day 27: 计算右侧小于当前元素的个数、翻转对
  • Linux wlan 之网络问题定位分析 实例一
  • 如何确定虚拟机的IP