springmvc源码解析

SpringMVC源码分析 目录 1、SpringMVC架构图 2、SpringMVC初始化流程图 3、SpringMVC执行流程图 4、SpringMVC组件解析 5、SpringMVC的工作机制 6、源码分析 6.1 初始化流程 6.2 请求执行流程 7、谈谈SpringMVC的优化 1、SpringMVC架构图 2、SpringMVC初始化流程图 3、SpringMVC执行流程图 用户发送请求至前端控制器DispatcherServlet。 DispatcherServl. 阅读详情

总结:

首先请求进入DispatcherServlet 由DispatcherServlet 从HandlerMappings中提取对应的Handler
 
 此时只是获取到了对应的Handle,然后得去寻找对应的适配器,即:HandlerAdapter
  拿到对应HandlerAdapter时,这时候开始调用对应的Handler处理业务逻辑了(这时候实际上已经执行完了我们 的Controller) 执行完成之后返回一个ModeAndView

 这时候交给我们的ViewResolver通过视图名称查找出对应的视图然后返回
  最后 渲染视图 返回渲染后的视图 -->响应请求

实例:

 在pom.xml文件上添加spring-mvc的依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.8.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
添加App类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author wufei
 * @create 2018-12-24 9:37
 **/
@ComponentScan("com.wf.spring.mvc")
@Configuration
public class App {
}

添加DispatcherServlet类

/**
 * 添加DispatcherServlet
 * @author wufei
 * @create 2018-12-24 9:47
 **/
public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletCxt) {
        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");

    }
}
/**
 * 第一种方式注册controller
 * 使用bean的形成注册controller
 * @author wufei
 * @create 2018-12-24 9:58
 **/
@Component("/test")
public class BeanController implements Controller{
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        System.out.println("test");
        return null;
    }
}
/**
 * 第二种方式注册controller
 * annotation形式注册controller
 * RequestMappingHandlerMapping
 * @author wufei
 * @create 2018-12-24 15:10
 **/
@Controller
public class AnnotationController {

    @RequestMapping("/test1")
    public String test(){
        System.out.println("test1");
        return "test1";
    }
}

源码分析:

首先我们看下DispatcherServlet继承关系图:

从图中可以看出DispatcherServlet最终继承的是个HttpServlet,即DispatcherServlet就是个Servlet。由此我们可以找到Servlet的doGet、doPost、service重要方法。在FrameworkServlet类中可以看到

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
        super.service(request, response);
    } else {
        this.processRequest(request, response);
    }

}

protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}

从三个方法上可以看出,都是调用了processRequest(request, response);方法,然后我们继续跟踪processRequest方法上

我们可以看到doService方法

 

该方法是个抽象方法,由DispatcherServlet类实现该方法的具体逻辑。发现有个重要的关键代码方法this.doDispatch(request, response);

进入doDispatch方法里面

看到两个最重要的方法,getHandler(处理器)和getHandlerAdapter(适配器)

问题1 handler从哪来的呢

我们先查看getHandler方法里面的代码

@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        Iterator var2 = this.handlerMappings.iterator();
        while(var2.hasNext()) {
            HandlerMapping hm = (HandlerMapping)var2.next();
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
            }

            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }

    return null;
}
是在迭代handlerMappings,而handlerMappings是个List集合
@Nullable
private List<HandlerMapping> handlerMappings;

handlerMapping存放两个值,一个是org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,一个是org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

 

问题2 handlerMapping是什么?

我们端个点,查看下具体是什么

如图所示:是两个我们不认识的东西,我们继续往下看,

HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
    return handler;
}

从mappings获取一个handler,然后返回了。

 

我们发现 handler就是我们的controll类的方法,我们以Bean的形式注册的Controller 可以从这个BeanNameUrlHandlerMapping里面 获取到对应的Handler ; 这里 我们是不是对于这个HandlerMapping有了懵懂的了解了

下面我们以Annotation方式注册的Controller,就会被第二个RequestMappingHandlerMapping获取对应的handler。如图所示:

问题3 什么是适配器

首先我们跟踪下代码

HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        Iterator var2 = this.handlerAdapters.iterator();

        while(var2.hasNext()) {
            HandlerAdapter ha = (HandlerAdapter)var2.next();
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler adapter [" + ha + "]");
            }

            if (ha.supports(handler)) {
                return ha;
            }
        }
    }

    throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

从代码上可以看出是迭代handlerAdapters,而这个从哪获取到的呢?也是从配置文件上获取的DispatcherServlet.properties

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
   org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
   org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

使用Annotation方式注册的Controller使用的是RequestMappingHandlerAdapter适配器

使用bean的形成注册controller使用的是SimpleControllerHandlerAdapter适配器

 

最后执行mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 执行业务逻辑了。输出了test1

然后返回mv,mv就是试图了,然后渲染页面。

适配器就是对应不同的handler有不同的解决方案

 

总结 
其实我们的SpringMVC关键的概念就在于Handler(处理器) 和Adapter(适配器)
  通过一个关键的HandlerMappings 找到合适处理你的Controller的Handler 然后再通过HandlerAdapters找到一 个合适的HandlerAdapter 来执行Handler即Controller里面的逻辑。 最后再返回ModlAndView...
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SpringMVC重点功能底层源码解析 SpringMVC在进行把String转成User对象时,会先判断有没有User类型对应的StringToUserEditor,如果有就会利用它来把String转成User对象,如果没有则会找User类中有没有String类型参数的构造方法,如果有则用该构造方法来构造出User对象。 阅读详情

相关推荐

闲鱼x-sign、x-mini-wua、x-umt三字段协同验证机制解析

在移动客户端风控体系中,设备标识与行为签名是保障接口安全的核心技术。x-sign并非传统时间戳+密钥的静态签名,而是融合设备特征、运行时状态与服务端动态因子的多阶段位运算结果;x-mini-wua作为小程序轻量水印,依赖主App注入的短时效sessionKey与截断时间戳;x-umt则通过设备硬件与网络环境联合编码实现强绑定。三者构成‘设备—环境—行为’三位一体的交叉验证链路,广泛应用于电商API防护、二手平台数据采集及自动化运营等场景。本文基于Android/iOS真机逆向与Frida动态分析,揭示其生成

weixin_30457551的博客 426

SpringMVC源码解析

文章目录一、主要组件二、DispatcherServlet初始化过程1)结构体系2)通过requestMapping注解(url)获取controller总结:三、DispatcherServlet处理请求过程2)获取处理器映射器结果2)处理器适配器3)视图渲染==总结== 一、主要组件 DispatcherServlet:前端控制器,统一处理请求和响应,整个流程控制的中心,由它调用其他组件处理用户请求。 HandlerMapping:处理器映射器,根据请求的url、method等信息查找Handler,

从基础到源码解析的学习记录 2062

LaTeX小白必看:5分钟搞定GB/T 7714-2005参考文献格式(Texmaker+BibTeX实战)

本文为LaTeX初学者提供了使用Texmaker编辑器和BibTeX工具链,快速实现GB/T 7714-2005参考文献格式的实战指南。文章详细解析了从获取gbt7714-2005.bst样式文件、编写.bib数据库到四步编译流程的核心步骤,并附有常见问题解决方案,帮助用户高效、准确地完成学术论文的参考文献排版。

weixin_29295541的博客 338

SpringMvc源码全解

文章目录一、SpringMVC请求处理流程2、 一、SpringMVC请求处理流程 SpringMVC的核心组件和请求处理流程如下: 1、 DispatcherServlet是SpringMVC中的前端控制器(front controller),负责接收request并将request转发给对应的处理组件。 2、HanlerMapping是SpringMVC中完成url到Controller映射的组件。DispatcherServlet接收request,然后从HandlerMapping查找处

weixin_38650898的博客 4308

《生成式AI引发的“认知污染”:社交媒体虚假信息的治理困局》

认知污染与生成式AI“认知污染”指信息环境被大量虚假、误导性内容所充斥,干扰公众对事实的认知判断。在社交媒体时代,虚假信息的生产和传播门槛大幅降低,呈现出工业化、规模化的趋势。近年兴起的生成式人工智能(Generative AI)技术,如大型语言模型(LLM)和深度伪造(deepfake),更是加剧了这一问题。AI可以自动生成看似真实的文本、图像、音视频,将虚假信息批量生产并快速散播到社交平台上。

那谁的博客 5915

解决用VScode写中文注释,Vivado打开之后是乱码的方法

这样就解决了中文注释乱码的问题,此外如果使用notepad++写verilog代码的话直接在notepad++上面将编码格式改为ANSI格式即可,更加方便快捷,所以此方法仅针对习惯用VScode写Verilog的同学,如果有其他好办法的话欢迎评论区补充。首先,VScode中的中文默认编码格式是UTF-8,然后Vivado的编码格式是vivado 默认的应该是ANSI编码格式,刚开始我先按照网上说明的,将VScode中的编码格式改为GBK格式(点击右下角->点击通过编码保存)。

weixin_50573305的博客 5816

Spring MVC源码分析

一、SpringMVC请求处理流程 在阅读源码之前先进行SpringMVC源码环境的搭建SpringMVC环境搭建 里面也对Controller控制器的几种实现方式,进行了简单说明,便于我们后续的理解。 下面也给一张流程图,方便我们进行梳理。 DispatcherServlet:DispatcherServlet是SpringMVC中的前端控制器,负责接收request并将request转发给对应的处理组件。 HandlerMapping:HanlerMapping是SpringMVC.

Jak的博客 5558

卫星通信链路预算实战:从EIRP到Eb/N0的完整计算指南(含Excel模板)

本文提供了一份卫星通信链路预算的实战指南,详细解析了从EIRP到Eb/N0的完整计算流程。文章重点对比了C波段与Ku波段在应对降雨衰减等动态因素时的不同策略,并分享了包含核心公式的Excel模板,帮助工程师将理论转化为可执行的系统设计依据。

weixin_29230773的博客 535

超详细SpringMVC源码剖析

Nullable= null) {for (ViewResolver viewResolver : this.viewResolvers) {//viewResolvers存放了两个视图解析器(1)InternalResourceViewResolver默认视图解析器 (2)BeanNameViewResolver自定义视图解析器if (view!= null) {//如果返回的视图为空,那么会继续遍历所有的视图解析器;

m0_59084856的博客 2760

【eNSP 华为模拟器】小型校园网模拟环境的设计与配置(附eNSP源文件)

【eNSP 华为模拟器】小型校园网模拟环境的设计与配置 一、实验概述 二、交换机的配置 2.1 二层交换机的配置 2.2 三层交换机的配置 三、路由器的配置 四、实验结果 五、实验总结 一、实验概述 按照以下的拓扑连接,自行设计VLAN和IP地址等网络参数,实现PC1到PC2的IP通信。其中,R1,R2为路由器;LSW1,LSW4为3层交换机;LSW2,LSW3 ,LSW6, LSW7为2层交换机;CLIENT1-CLIENT12为PC机。 拓扑图 课程设计要求:(1)IP地址自行规划设计,应该清晰地

qq_43757282的博客 4万+

基于 C# 实现 RTSP 摄像头监控分屏系统:从流媒体获取到多画面显示

通过本文的讲解,我们介绍了如何在 C# 中实现 RTSP 摄像头监控分屏系统。我们使用了FFmpeg和VLC两种不同的方法来获取和解码 RTSP 流,并通过PictureBox控件和控件实现了分屏布局。两种解码方案都非常强大,可以根据实际需求选择最适合的方案。通过这种方式,您可以轻松地在 C# 中集成 RTSP 流,并将多个摄像头的视频流实时显示在同一屏幕上,进行监控和分析。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 2309

SpringMVC的源码解析

springmvc、springboot、源码解析

蓝影铁哥的博客 1191

Qt入门教程100篇(已完结)

Qt5入门教程,Qt6入门教程。包含了: Qt环境搭建篇、Qt数据类型篇、Qt中STL篇、Qt核心篇、Qt核心对象QObject篇、Qt基础控件篇、Qt对话框篇、Qt高级控件篇、Qt数据模型篇、QSS篇、Qt文件篇 、Qt硬件编程、Qt的一些demo、Qt项目开发篇。......

小鱼酱的博客 15万+

SpringMVC 源码解析

SpringMVC 源码解析 文章目录SpringMVC 源码解析@[toc]完成 Handler - Controller 控制器的方式服务器加载时核心方法的入口doDispatch 源码解析流程总结 图为网上别人的,只可以用来参考,最终真正的运行流程还是要通过自己的源码 debug 来进行理解。 完成 Handler - Controller 控制器的方式 使用注解方式 实现 Controller 接口 实现 HttpRequestHeader 接口 实现接口的方法是 BeanName 的方式

qq_44684668的博客 485

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

SpringMVC源码解析——HTTP请求处理

这个函数是一个公共方法,它调用了其他的方法来处理HTTP请求,并根据处理结果进行相应的操作。如果返回值为null,它会判断请求是否未修改、响应状态是否为null或请求是否已处理,如果满足条件,则设置请求已处理并返回。媒体类型包括在请求映射中指定的可生成媒体类型、能够写入特定返回值的配置转换器的媒体类型,或者所有媒体类型。函数首先从请求中获取可生成媒体类型集合,如果不为空,则直接返回该集合。否则,函数遍历所有消息转换器,判断是否能够写入特定返回值,如果可以,则将支持的媒体类型添加到结果集中。

qq_16500963的博客 1228

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

SpringMVC中视图解析器源码分析

SpringMVC中视图解析器源码分析 该篇博客只分析视图解析器源码,如果想看DispatcherServlet的具体流程,请看SpringMVC中DispatcherServlet源码 直接进入视图解析的入口,如下 进入该方法 关键的一行代码如上,进入render()方法 protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {

liujiqing123的博客 335

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

springmvc源码深度解析

文章目录springmvc源码深度解析工程代码入口及重要方法getHandler方法getHandlerAdapter方法及适配器模式handle方法及视图解析总结 springmvc源码深度解析 工程代码 建议先精读springmvc零配置原理 pom文件 依赖 <dependency> <groupId>org.springframework</gro...

LiuRenyou的博客 1191

SpringMVC执行流程、Servlet执行流程 、SpringMVC源码解析

SpringMVC执行流程、Servlet执行流程 、SpringMVC源码解析

洛柒 556

SpringMVC源码阅读:Controller中参数解析

  1.前言 SpringMVC是目前J2EE平台的主流Web框架本文将通过源码(基于Spring4.3.7)分析,弄清楚Controller是如何匹配我们传入的参数,并定义简单的参数解析器 2.源码分析 doDispatch方法943行获取了HandlerAdapter,ctrl+h打开类继承图,找到RequestMappingHandlerAdapter,RequestMappin...

weixin_44048532的博客 797

SpringMvc源码解析

一,SpringMvc源码解析 1.1核心流程图解 1、用户发送请求至前端控制器DispatcherServlet 2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。 4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器 5、执行处理器(Controller,也叫后端控制器)。 6、Co

宇轩笔墨 1268

SpringMVC请求处理源码解析

SpringMVC请求处理源码解析

2303_76379322的博客 929

SpringMVC源码之参数解析绑定原理

摘要 本文从源码层面简单讲解SpringMVC的参数绑定原理 SpringMVC参数绑定相关组件的初始化过程 在理解初始化之前,先来认识一个接口 HandlerMethodArgumentResolver 方法参数解析器接口,这个接口是SpringMVC参数解析绑定的核心接口。不同的参数类型绑定都是通过实现这个接口来实现。也可以通过实现这个接口来自定义参数解析器。这个接口中有如下两个方法...

vwycm的博客 980

回溯算法实战:括号生成与全排列的决策树与剪枝解析

回溯算法是解决组合优化问题的核心方法,其本质是通过决策树遍历所有可能解,并利用剪枝提前排除无效分支。在LeetCode括号生成与全排列问题中,选择列表的动态性决定了循环结构:固定选择用条件判断,动态选择用for循环枚举。理解决策树形状与剪枝条件推导,能显著提升算法效率与代码正确性。掌握这一框架后,可轻松应对组合总和、子集等变体,是算法面试与工程实践中的高频考点。

weixin_34160277的博客 393
上一篇: Hadoop集群搭建
下一篇: linux常用命令
wflovejava
博客等级 码龄11年 23粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值