SpringMVC的源码解析

发布时间 - 2026-01-10 22:56:04    点击率:

学习java的人都知道spring,springMVC,mybatis等框架,像structs2这样的框架是基于servlet以外实现的,而springMVC是基于servlet容器实现的,

本文将分析SpringMVC的核心分发器DispatcherServlet的初始化过程以及处理请求的过程,让读者了解这个入口Servlet的作用。

在分析DispatcherServlet之前,我们先看下DispatcherServlet的继承关系,

HttpSerlvetBean继承自HttpServlet。

HttpServletBean覆写了init方法,对初始化过程做了一些处理。 以下是初始化的代码:

首先,ServletConfigPropertyValues是HttpServletBean的静态类,构造过程会使用ServletConfig对象找出web.xml文件中配置参数,并设置到ServletConfigPropertyValue,使用BeanWrapper来构造DispatcherServlet, 获取ServletContextResourceLoader的资源加载器,然后注册资源编辑器,初始化BeanWrapper对象,设置DispatcherServlet属性,默认初始化ServletBean不做任何处理,子类覆盖该方法可以做任何事情,

以下是web.xml文件配置:

这段配置初始化参数为contextConfigLocation,后来构造的是BeanWrapper对象, 由于contextConfigLocation在FrameworkServlet中定义,但是没有在HttpServletBean中定义,利用Spring的注入特性,只需要调用setContextConfigLocation方法,就可以将contextConfigLocation设置到对应的实例当中,然后设置DispatcherServlet中contextConfigLocation(FrameworkServlet中定义)的属性,为web.xml读取contextConfigLocation参数,该资源文件用构造SpringMVC的容器的上下文。

下面看下FrameworkServlet这个类,FrameworkServlet继承自HttpServletBean。

以下是initServletBean的代码:

首先第一步是初始化WebApplicationContext,它是继承于ApplcationContext的接口,ApplcationContext是Spring容器的上下文,Servlet和Spring容器关联的作用,然后初始化FrameWorkServlet,其实它空的,什么也做,子类重写这个方法,可以做任何处理,不过DispatcherServlet并重写这个方法。

下面是初始化initWebApplicationContext的具体实现逻辑: 

    

首先,得到根路径,DistpatcherServlet有个WebApplication为参数的构造函数,如果注入了WebApplication 这个对象,就会执行上图代码。

FrameworkServlet中有个String类型的contextAttribute的变量名,以它为key在ServletContextWebApplicationContext,一般不会设置,contextAttribute属性,也就说,wac开始是null;接下来就是创建WebApplicationContext,并设置根上下文为父上下文,然后配置ServletConfig,ServletContext等到这个上下文,这个类中有个函数onReFresh是一个模版方法,在WebApplication成功创建后就会调用,FrameworkServlet的实现类,就会重写这个方法,并将创建的容器上下文设置到ServletContext中,这里的根上下文是web.xml中配置的ContextLoaderListener监听器中根据contextConfigLocation路径生成的上下文。

比如这段配置文件中根据classpath:context-*.xml下的xml文件生成的根上下文。

接着看一下DispatcherServlet重写了FrameworkServlet中onReFresh方法,

可以看到initStrategies方法中,在初始化各种各种策略接口的实现类, 后面再一一分析各个策略接口的实现的详细介绍。

总结一个三个类的作用:

HttpServletBean 主要做一些初始化的工作,将web.xml中配置的参数设置到Servlet中。比如servlet标签的子标签init-param标签中配置的参数。

FrameworkServlet 将Servlet与Spring容器上下文关联。其实也就是初始化FrameworkServlet的属性webApplicationContext,这个属性代表SpringMVC上下文,它有个父类上下文,web.xml中配置的ContextLoaderListener监听器初始化的容器上下文。

DispatcherServlet 主要是初始化一些各个策略接口的实现。比如请求处理,试图处理。处理的适配等。

DispatcherServlet请求处理过程:

先看下HttpServlet提供的方法用于处理请求,service使用了模版模式,对于HttpServlet的get请求,调用doGet方法,post请 求,调用doPost方法........

在看下处理processRequest函数

首先,获取于当前线程绑定的LocaleContext和ServletRequestAttributes对象,initContextHoers函数就是让新构造的LocaleContex和requestAttributes进行关联,这个关联使用ThreadLocal完成,doService方法是抽象方法,具体由DispatcherServlet实现。

最后调用resetContextHolders函数重置LocaleContext和RequestAttribute对象,解除LocaleContext和RequestAttribute对象的绑定。执行成功后,发布ServletRequestHandlerEvent事件,可以通过注册监听器来监听该事件的发布。注册的监听器类型为ApplicationListener接口类型。

接下来是DispatcherServlet的doService方法.

如果该请求是include的请求,那么保留一份快照版本的request域中的数据,doDispatch方法之后,这个快照版本的数据将会覆盖新的Requet域的数据。  

然后在request中设置一些属性,最后doDispatcher进行请求分发处理。      

doDispatch方法功能大致过程如下:

首先根据请求的路径,通过RequestMapping的注解映射,找到HandlerMethod(也就是对应Controller中的方法),然后匹配路径对应的拦截器,有了HandlerMethod和拦截器构造个HandlerExecutionChain对象。HandlerExecutionChain对象的获取是通过HandlerMapping接口提供的方法中得到。

有了HandlerExecutionChain之后,通过handlerAdapter对象进行适配处理,得到ModelAndView对象,HandlerMethod内部handle的时候,使用各种HandlerMethodArgumentResolver实现类处理HandlerMethod的参数,使用各种HandlerMethodReturnValueHandler实现类处理返回值,最终返回值被处理成一个ModelAndView对象,这期间发生的异常会被HandlerExceptionResolver接口实现类进行处理.

总结: 本文主要分析DispatcherServlet及其父类FrameworkServlet和HttpServletBean它们的作用。以及一个请求到处理返回,大致过程的分析。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# SpringMVC  # Spring+SpringMVC+JDBC实现登录的示例(附源码)  # Spring MVC 启动过程源码分析详解  # SpringMVC源码解析之消息转换器HttpMessageConverter  # Spring SpringMVC在启动完成后执行方法源码解析  # spring MVC cors跨域实现源码解析  # 从源码角度看spring mvc的请求处理过程  # 有个  # 就会  # 重写  # 子类  # 这段  # 写了  # 绑定  # 先看  # 返回值  # 的是  # 是一个  # 拦截器  # 将会  # 是基于  # 它是  # 的人都  # 可以通过  # 并将  # 可以看到  # 详细介绍 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Python自动化办公教程_ExcelWordPDF批量处理案例  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  Laravel中的Facade(门面)到底是什么原理  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  Swift中swift中的switch 语句  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  JavaScript如何实现路由_前端路由原理是什么  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  Laravel如何实现用户注册和登录?(Auth脚手架指南)  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  LinuxShell函数封装方法_脚本复用设计思路【教程】  Laravel如何与Inertia.js和Vue/React构建现代单页应用  郑州企业网站制作公司,郑州招聘网站有哪些?  Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】  如何快速搭建自助建站会员专属系统?  使用PHP下载CSS文件中的所有图片【几行代码即可实现】  Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案  Laravel如何使用Collections进行数据处理?(实用方法示例)  JavaScript如何实现倒计时_时间函数如何精确控制  Laravel中的withCount方法怎么高效统计关联模型数量  Laravel如何实现模型的全局作用域?(Global Scope示例)  C语言设计一个闪闪的圣诞树  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  如何在宝塔面板中创建新站点?  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  个人摄影网站制作流程,摄影爱好者都去什么网站?  如何快速完成中国万网建站详细流程?  JavaScript如何实现继承_有哪些常用方法  Laravel如何创建自定义中间件?(Middleware代码示例)  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  javascript如何操作浏览器历史记录_怎样实现无刷新导航  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  如何自定义建站之星网站的导航菜单样式?  Laravel如何升级到最新版本?(升级指南和步骤)  Laravel如何连接多个数据库_Laravel多数据库连接配置与切换教程  如何在建站之星网店版论坛获取技术支持?  Android Socket接口实现即时通讯实例代码  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道  免费视频制作网站,更新又快又好的免费电影网站?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  如何快速生成高效建站系统源代码?  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  Laravel如何与Pusher实现实时通信?(WebSocket示例)