SpringMvc 源码解析

图1

首先加入 spring——webmvc依赖。

图2

首先我们要明白一个请求的过程。一个request 请求 首先经过一个 servlet 。然后同反射获取类名和方法名,调用controller类的对应方法。

图3

图4

 

setLonadOnStartup(1) 的作用是回执行DispatcherServlet的init()方法。

图5

 图6

这个是tomcat启动的时候调用的过程。不好分析代码。我们从页面调用一下controller来跟踪。

图7

这个是DispatchServlet的类图。

图8

图9

通过调用链,我们能够看首先调用的是FrameworkServlet的service 方法,然后调用HttpServlet的service方法,调用FrameworkServlet的doGet方法。在调用FrameworkServlet的processRequest方法, 这些都不重要。

这些都是一些变量的赋值不重要。

 

这个是核心方法。

图10

 

 978行推断controller的类型,啥?controller还有类型,都用哪几种类型啊,3种类型。

 如果HandlerExecutionChain是一个bean,appedHandler.getHandler()是一个类,如果是一个方法,appedHandler.getHandler()返回的就是一个方法。现在有问题,如果是一个类的情况,为什么不能也返回一个 handleRequest() 这个一个方法,因为肯定会实现这个方法的啊。 最终把获取的类,或者方法交给HandlerAdapter的适配器去处理。不同的方法交给不同的适配器。这个适配器分为两个大类一个处理url的,另一个是处理bean的。图14

前置拦截器处理。

采用反射调用。

图10-0

 

图10-1

这个是加@Controller注解的;

 

这个两种的实现方法有什么不同呢。 如果是实现Controller接口的方法,回重写hadleRequest方法。我们只需从map1中找到路径 key为luban,对应的value值的IndexController就可以了。直接通过反射调用Controller的hadleRequest方法就可以了,因为这个是固定写死的。

但是我们加@Controller 注解的方式,不实现Controller接口。这样我们就不能固定找到对应的方法了。因为方法会变的。首先spring根据路径localhost:9090/index  ,从map1中找对应index的key ,从map1中找不到,然后再从map2中找到找到了index对应的方法,index1,利用反射调用这个index1()方法。 spirng 中map1和map2 是用HanderMapping 子类来实现的。

 

图10-2

图11

BeanNameUrlHandlerMapping 顾名思义就是和我们类的名称有关对应的是我们上面说的map1。 下面的RequestMappingHandlerMapping 与我们的请求路径有关相当于与上面的map2。当我们是使用第二种方式的时候,加了@Controller注解方式的时候,当遍历haderMappings时,BeanNameUrlHandlerMapping 应该为null值,继续遍历requestMappingHandlerMapping应该有两个两个值,一个是key为index,value为index;一个是key是index2,value是index2的值,

图12

 

第一种方式实现Controller接口。当我们是使用第一种种方式的时候 当遍历haderMappings时,BeanNameUrlHandlerMapping 应该为key为tiger,value为TingerController 结束循环。返回。现在问题来了haderMappings在什么时候初始化的呢,图15

 

图13

HandlerMapping的作用是确定handler的类型是方法,还是类。

 

图14

图15

 

 

图16

图17

 

图18

图19

图20

图21

handerMapping 是从配置文件中获取,图22

图22

图23

上传的时候这个名字是固定的multipartResolver 这个。上传的时候bean名字一定要是这个要不然spring没有办法初始化完成。

 

图24

598行 先从singleObject中 拿出来所有的handlerMapping,如果是springMVC handlerMapping一定是空。所以下面599行不会进入。

图25

如果从singleObject中拿出的handlerMappings为空,从配置文件中获取默认的那两个.图26 

图26

图27

 

配置文件中默认的两个hadlemapping.  

图28

 现在有一个场景; 三个请求一个 请求是index.do  ,一个是index.html。一个是tiger.do  。 index.do。交给dispatchServlet的 首先通过/inex,去BeanNameUrlHandlerMaping 查询对应的key 查询不到,然后再从 Request MappingHandlerMapping中  map2中匹配到可以以映射到一个adpter适配器 去处理转化 成json返回.  ,tiger.do 通过map2 就是BeanNaemUrlHandlerMapping 映射到对应的adpter适配器,去处理对应的请求。index.html 请求要返回一个 html.这个怎么办法,从map1和map2也就是对应的 BeanNameUrlHandlerMapping和RequestMappingHandlerMapping中获取不到对应的 适配器,咋办? springboot是咋做的呢, 

图29

图30

 

图31 

图32 

图33

 

通过这个代码我们能够知道这个hanlerMap相当于map1 ,问题来了,这个map1是什么时候示例化的呢,

 

图34

图35

这个handler为null. 自己写个hander来实现 response 一个html出去。,怎么放进spring容器中呢,

图36

springboot   如果是/index.html 他首先 BeanNameUrlHandlerMapping中匹配,如果匹配到返回对应的适配器去处理返回。,匹配不到 ,匹配RequestMappingHandlerMapping ,如果匹配到返回对应的适配器处理。如果匹配不到 判断是否符合/* 符合匹配springboot的handler ,如果不符合/* 直接404找不到。

图37

首先从hadlerMapping重 singletonObject 中获取,获取不到再从配置文件获取。那springboot 是怎么做的呢,是这样做的吗,我们一起看下。

图38

 启动spring boot

图39

图39-0

 

图40

图41

这个时候我们发现handlerMappings中有5个值。 除了默认的BeanNameUrlHandlerMapping ,和RequestMappingHandlerMapping中,还多了三个。其中两个SimpleUrlHandlerMapping处理的东西不一致。那么真正能够处理我们index.html是那个呢。

图42

通过断点我们知道真正处理我们index.html是 第四个SimpleUrlHandleMapping 

t图43

图44

图45

/webjars 和 /* 

 

1

176行依次遍历map 中的/webjars 和 /*  ,利用正则表达式和/index.html进行匹配,通过遍历到/*和index.html匹配成功后放入matchingPatterns集合中。

 

 

 

图46

当我们访问index 这样正常的流程呢,

图47

1033行执行前置拦截器, 

 

图48

图49

图50

调用invokerHandlerMethod。

图51

 

图52

 

图53

图54

图55

反射调用到我们的IndexController类的index()方法。

图56

图57

图58

 图59

不同的handler 处理不同的返回结果,比如有返回json的,有返回字符串的,有返回modleAndView的。

图60

对监听器的那个监听事件感兴趣。相当于订阅了摸个事件。 

图61

图62

 

图63

 

 图64

如果只有一个参数的话,比较好处理直接从requst的map中取出name ,进行反射调用就可以了。

如果是两个参数就比较麻烦了,因为controller经过编译后会成 index(s1,s2) 这种类型,没有办法知道到底哪个是名称,哪个是岁数。

这个需要用字节码技术来实现。

图65

这种情况spring mvc 怎么处理。

图66

图67

图68

图69

图69

 

 




图70

 

 

Spring boot 的requestMappingHandlerMapping,  是从容器中获得的。但是在spring中我们发现requestMappingHandlerMapping并不在容器中。而是从容器中获取失败后,再从配置文件中加载。那问题来了到底springboot是什么时候放入的呢,,

图71

断点后跟踪 确实是put进去了。

图72

图73

 

 

ConfigurantionClassBeanDefintion 这个类。

图74

 

通过分析WebMvcAutoConfiguration 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值