由于疫情的原因,今年的清明节实属凄凉,让我们为负重前行的英雄们,默哀。。。。
一直在用Spring,但是从来没考虑过前端的请求是如何调用到Controller中的方法的,只在网上看看别人的回答,今天呢,游戏也不让玩,闲来无事翻了翻Spring请求的源码,在此做个小总结:
网图整楼
作为一名优秀的JAVA开发工程师,对这张图大家应该都不陌生:首先前端控制器接收请求,然后前端控制器调用处理器映射器…
朗朗上口,倒背如流。但是真要问知其所以然,恐怕大家都一脸懵逼。例如,前端控制器如何拦截请求?懵了吧,来,和我一起读读源码!
前端控制器DispatcherServlet是如何进行加载的?
第一步,我们先找到前端控制器(DispatherServlet),这里我拿到了他的所有父类,看图:
好,既然他是个Servlet,那么在系统启动时,必然会走init初始化方法,那么它会走哪个类中的init方法呢?我们一一从上往下找:
HttpServlet中没有重写init方法;
显然,上面的类的init方法都是为空的,说明都需要子类来重写,直到HttpServletBean才开始重写init方法。
第二步:在HttpServletBean中打断点,如上图;
第三步:我们启动项目,断点顺利停住请求,说明我们的思路没有错误。
于是我们看看当前方法里面走了啥,它主要走的是initServletBean()方法,当前类的该方法为空,那我们看它的子类FrameworkServlet所实现的initServletBean方法!
FrameworkServlet所实现的initServletBean方法主要走了两个方法,分别是:initWebApplicationContext()和initFrameworkServlet(),我们一一来看:
首先initWebApplicationContext()
继续往下走,看他还做了什么,我们发现他走了onRefresh()方法:
那么这个onRefresh()方法又走向什么呢?
当前类中方法为空,说明需要子类来实现,由此,我们就进入到了前端控制器!
这些方法名称看着眼熟不?
用户发送一个请求,如何找到对应的controller(执行流程)?
刚刚展现的是DispatcherServlet在项目启动时,会调用它的init方法,有且仅调用一次,那么在接收一个请求时会走的时service方法!(PS:servlet基础知识)
由此可见,service方法最终还是根据请求方式的不同,被分发到不同的doGet、doPost…方法中;
PS:这里注意一下,由于我们请求的方式是以@RequestMapping("/test.do")的注解方式,所以我们这里返回的也是一个对应的方法,如果是另外的基于bean名称的访问方式,那么放回的是对应的类!
PS:走到这里,我很奇怪,怎么也进不去Controller层。讲道理,Handler应该有个入口方法,会去调用Controller层对应的方法。试了好久都没找到入口。于是我用上了前面的基于Bean名称的方式。
新建一个Bean:
浏览器访问:
直接来到处理器适配器调用处理器的位置:
进去,发现和上面那种方式的方法不一样:
然后,再点进去,惊喜:
顺利读到了Controller层!然后可以执行项目中的方法。。。
至于后面的视图解析啥的,我就不看了,想来应该不会很麻烦,无非将结果拆分解析最后映射到页面上,对这个好奇心不大(主要还是该恰饭了。。),有兴趣的小伙伴自行阅读哟。
还有一个就是,使用注解的方式,我在适配器调用处理器的时候还是找不到进入Controller层的入口,知道的小伙伴帮忙解释一波,万分感谢!
此致,敬礼!