「⾯试⾼频题」SpringMVC执⾏流程
SpringMVC执⾏流程
SpringMVC概述
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow⾥⾯。Spring 框架提供了构建
Web 应⽤程序的全功能 MVC 模块。使⽤ Spring 可插⼊的 MVC
架构,从⽽在使⽤Spring进⾏WEB开发时,可以选择使⽤Spring的Spring MVC框架或集成其他MVC开发框架。
SpringMVC执⾏流程概括
SpringMVC框架固然强⼤,但是其执⾏流程更是妙不可⾔。所以我们这次要⽤⼀个简单的例⼦去深究⼀下SpringMVC的底层执⾏流程!
如下是SpringMVC的执⾏流程梗概图,我会在后⾯的底层流程剖析中重点提到梗概图中的这⼏个零件,以及它们的作⽤!
SpringMVC执⾏流程梗概图(切记:该图只是梳理思路,并不特别严谨,请谅解)
SpringMVC的重要组件(可视化组件)
既然,我们要选择剖析SpringMVC底层执⾏流程,那肯定是要先分析我们能所看到表⾯的MVC重要组件。这样我们分析完可视组件后,就能到分析SpringMVC底层执⾏流程的⼊⼝,所以分析它的重要组件显得更是重要!
SpringMVC的重要组件是由核⼼的前端控制器(l)、后端控制器(Controller)和l配置⽂件组成。
核⼼的前端控制器: 作为MVC框架,⾸先要解决的就是如何能收到请求。所以MVC框架⼤都会设计⼀款前端控制器(⼊⼝或者说起点),选型在Servlet或Filter两者之⼀,由前端控制器来最率先的⼯作,接收请求。在SpringMVC中,也不例外,前端控制器的选型确定为Servlet(DispatcherServlet),此前端控制器在接收请求后,还会负责SpringMVC的核⼼调度管理,所以既是前端⼜是核⼼。
后端控制器: 后端控制器为Controller,等价于之前定义的Servlet。MVC框架中,后端控制器也是必不可少的重要组件之⼀。因为它接收了⽤户请求的⼤量数据参数对象(或Json)存储在域中⽅便页⾯(JSP)取值,或是携带着这些数据返回所需要跳转(重定向或请求转发)的页⾯。这⾥值得注意的是,后端控制器本质并不是⼀个普通的Servlet,也不是BaseServlet,它只是⼀个普通的类,⾥⾯却像曾经的BaseServlet⼀样可以拥有很多个⽅法,这些⽅法在SpringMVC中成为⼀个个Handler(换汤不
换药,本质仍然)。所以在MVC模式的执⾏流程环节中,后端控制器控制着页⾯的跳转和数据的传递,在这⾥也有着很⾼的地位。
SpringMVC执⾏流程剖析
上述得知,我们执⾏流程剖析的⼊⼝既是核⼼的前端控制器,即l,那我们有资格了解该前端控制器中配置了什么!如下:
前端控制器
由上图所知,前端控制器中所包含的即是同时启动SpringMVC⼯⼚和Spring⼯⼚,让两个⼯⼚同时运作处理请求,并作出响应。既然要剖析SpringMVC的底层执⾏流程,那我们要从加载SpringMVC⼯⼚的DispatcherServlet说起。⾸先进⼊到DispatcherServlet中,查看源代码所有⽅法,如下图所⽰:
DispatcherServlet源码所有⽅法
DispatcherServlet继承FrameworkServlet
上图所⽰,我进⼊到了DispatcherServlet中。既然说它是⼀个Servlet,那肯定是需要寻它的service⽅法,因为Service⽅法是Servlet 的核⼼所在。于是我打开了IDEA的⽅法列表搜索service⽅法,未果。
虽然未果,但是我发现两个重要的线索,⼀是该Servlet中有⼀个doSerivce⽅法,⼆是DispatcherServlet继承了FrameworkServlet,我想既然⼦类没有service⽅法,⽗类肯定有,于是我进⼊到了FrameworkServlet查看源代码,如下图所⽰:
FrameworkServlet源码
我兴冲冲在⽗类(FrameworkServlet)中到了service⽅法,但是还是感觉⾼兴的太早了,该service
⽅法中除了resolve⽅法获取请求⽅式和processRequest⽅法外,我⼀⽆所知。随后竟然发现了红⾊箭头所指向的东西super.service(request, response);,这意味着什么呢?这意味着它继承了⽗类拥有的service⽅法,于是我点击super句点后⾯的service⽅法查看源码惊⼈的发现这个类竟然是HttpServlet,显然我们service⽅法的这条路⾛到尽头了。在⾥⾯有两个⽅法存在⼀个是resolve⽅法,它是获取请求⽅式的。还有⼀个⽅法不知道是做什么的,于是我点击了进去查看源码,如下图所⽰:
processRequest⽅法源码
既然我们进去看到了processRequest⽅法的源码,就要重要的⽅法。何为重要的⽅法呢,⼀般被try块包裹的⽅法必然是重要⽅法,于是我到了doService(request, response);⽅法,并继续点击去看该doService⽅法的源码,如下图所⽰:
doService(request, response);⽅法源码
逐渐失去耐⼼的我真的被惊讶到了,进⼊到doService⽅法后,也没有跳到其他的类中,⽽且还是在该类中跳到了⼀个空的doService();⽅法中。唉,探究究竟真的是件不容易的事情呀~我叹了⼀⼝⽓。冷静下来⼀想,⽗类是空⽅法没有实现,那核⼼逻辑代码必定是在⼦类中了呀。这不是多态嘛!于是,我得出了结论,费劲吧难,⼊⼝的逻辑代码回过头来还是得看DispatcherServlet中的那个doService⽅法。此时我知道,这必将是⼀个漫长的探索之路。于是,我秉着探究原理的⼼态,再⼀次点进了被我错过的那个DispatcherServlet中的doSerivce⽅法,如下图:
DispatcherServlet中的doService()⽅法
springmvc常用标签既然确定了这是探究底层原理的开始,那我们就在doServie()⽅法中寻重要的逻辑,于是我再⼀次的在try块中到了⼀个名为doDispatch(request, response);的⽅法(省略了前⾯的各种初始化和存储域数据)。在探究底层原理的道路上,你会发现越来越接近真理,虽然这注定是⼀个漫长的探索过程,我也情愿。于是,点击进⼊到了doDispatch()⽅法中的源码,如下图所⽰:
doDispatch()⽅法源码
⾛进了doDispatch()⽅法的源码,才知道我没有看错你。⾥⾯标有注释的都是⼀些重要的执⾏逻辑⽅法。接下来我们会⼀个个的分析,逐步深⼊理解SpringMVC的执⾏流程。既然探索执⾏流程那就少不了Debug(Debug调试功能,Debug能很清晰的看到执⾏流程),于是我在getHandler()⽅法的那⼀⾏打了⼀个断点。下⼀步跟进执⾏流程进⼊到了getHandler()⽅法,如下图所⽰:
getHandler⽅法源码(注释解释:为当前请求寻并返回⼀个handler对象)
断点停留到了这⼀⾏,因为getHandler()的名字,顾名思义就是获取Controller层中的Handler。它是怎么获取到的呢?我们在断点的变量显⽰框中,看到handlerMappings是⼀个数组,其中有三个对象。他们可以分别以不同的⽅式处理不同的Handler,其中我们可以点击这个三个对象,⼀⼀把其对象展开查看重要属性,如下图所⽰:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。