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

Spring MVC 之适配器模式

        Spring MVC 启动的关键流程我们已经学习了 Handler 与 HandlerMapping,还未掌握的小伙伴可以翻看前面的文章进行学习,今天我们将进入启动的第四步,了解 HandlerAdapter 的基本实现与作用。

d.png

HandlerAdapter的作用

         HandlerAdapter 的作用是将 HTTP 请求与控制器之间的接口进行转换。它接受一个处理请求的控制器(Handler,任何实现了Controller接口或者注解了 @Controller注解的类),并将请求的参数、请求的类型、响应的类型等信息适配给控制器进行处理,最终将处理结果封装成一个 ModelAndView 对象返回给 DispatcherServlet。

HandlerAdapter 的主要作用包括:

请求参数适配

        当 Handler 方法需要参数时,HandlerAdapter 会根据参数类型和名称,将请求中的参数适配给 Handler 的方法。例如,当 Handler 方法需要一个 String 类型的参数时,HandlerAdapter 会从请求中获取参数,并将其转换成 String 类型的参数传递给 Handler 的方法。

请求类型适配

        HandlerAdapter 还负责将请求的类型适配给 Handler。例如,当请求为 GET 请求时,HandlerAdapter 会调用控制器方法中的 GET 方法;当请求为 POST 请求时,HandlerAdapter 会调用 Handler 中的 POST 方法。

响应类型适配

        Handler 返回的结果通常应该是一个 ModelAndView 对象,因此 HandlerAdapter 负责将 Handler 的返回结果适配给 ModelAndView 对象。例如,当 Handler 返回一个字符串时,HandlerAdapter 会将该字符串封装成 ModelAndView 对象并返回给 DispatcherServlet。

HandlerAdapter 的源码实现

        HandlerAdapter 接口定义了一个方法,即 handle() 方法,用于处理请求并返回 ModelAndView 对象。

Spring MVC 框架提供了多个 HandlerAdapter 的实现类,主要包括以下几个:

HandlerAdapter
SimpleControllerHandlerAdapter
HttpRequestHandlerAdapter
AnnotationMethodHandlerAdapter
RequestMappingHandlerAdapter

下面以 RequestMappingHandlerAdapter 为例,介绍 HandlerAdapter 的源码实现。

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        ModelAndView mav = new ModelAndView();
        mav.setViewName(getViewName(handlerMethod));
        mav.addAllObjects(getModelAndView(handlerMethod, request, response));
        return mav;
    } else {
        throw new IllegalArgumentException("handler is not a HandlerMethod");
    }
}

        该方法接受三个参数:HttpServletRequestHttpServletResponseObject。其中,HttpServletRequest 和 HttpServletResponse 分别表示当前请求和响应对象,Object 表示当前请求所对应的 Handler 的 HandlerMethod 对象

handle() 方法中,

  1. 首先判断传入的 Handler 是否为 HandlerMethod 类型。
  2. 如果是,则强制转换为 HandlerMethod 对象,并初始化一个 ModelAndView 对象。
  3. 然后,通过 getViewName() 方法获取视图名称,并通过 getModelAndView() 方法获取控制器方法的参数值并封装成 ModelAndView 对象。
  4. 最后,将 ModelAndView 对象返回给 DispatcherServlet。

总结

        HandlerAdapter 通过适配器模式将 HTTP 请求与 Handler 之间的接口进行转换,从而实现了请求的分发和处理。

         HandlerAdapter 通过 handle() 方法将请求参数适配给 Handler 参数,将请求的类型适配给 Handler,将响应的类型适配给 ModelAndView 对象,并最终将 ModelAndView 对象返回给 DispatcherServlet。

         Spring MVC 框架提供了多个 HandlerAdapter 的实现类,其中最常用的是 RequestMappingHandlerAdapter。RequestMappingHandlerAdapter 支持使用 @RequestMapping 注解来定义请求映射。

相关文章:

  • 八大排序算法总结
  • 【2023年4月美赛加赛】Y题:Understanding Used Sailboat Prices 建模思路、建模方案、数据来源、相关资料、Python代码
  • 区块链基础知识
  • Vue3学习笔记:了解并使用Pinia状态管理
  • 测试行业3年经验,从大厂裸辞后,面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生
  • 【计组】性能指标——速度
  • 第一章 信息资源管理基础
  • java真有一个关键字叫strictfp啊
  • MySQL OCP888题解069-CHECK TABLE
  • Redis 官方可视化工具-RedisInsight
  • 基于springboot实现财务管理系统【源码+论文】分享
  • Parasoft帮助中移智行顺利获得A-SPICE L3和ISO26262功能安全认证证书
  • 计算机组成 --- 计算机系统的多级层次结构
  • 新六级通关训练
  • Python是不是被严重高估了?
  • [NodeJS] 关于Buffer
  • [数据结构]链表的实现在PHP中
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • JavaScript对象详解
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Next.js之基础概念(二)
  • Redis在Web项目中的应用与实践
  • Ruby 2.x 源代码分析:扩展 概述
  • Webpack 4 学习01(基础配置)
  • 闭包--闭包之tab栏切换(四)
  • 服务器从安装到部署全过程(二)
  • 给第三方使用接口的 URL 签名实现
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 微信小程序设置上一页数据
  • 一道闭包题引发的思考
  • ionic入门之数据绑定显示-1
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • #{}和${}的区别?
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (04)odoo视图操作
  • (a /b)*c的值
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (九)One-Wire总线-DS18B20
  • (一)VirtualBox安装增强功能
  • (转)Oracle存储过程编写经验和优化措施
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .Net7 环境安装配置
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .NET建议使用的大小写命名原则
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @Transactional类内部访问失效原因详解
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku
  • []error LNK2001: unresolved external symbol _m
  • [Angular 基础] - 表单:响应式表单
  • [BZOJ 1032][JSOI2007]祖码Zuma(区间Dp)
  • [BZOJ4566][HAOI2016]找相同字符(SAM)