Spring-MVC源码执行流程加解释(新手小白自学的,肯定有错误,勿喷)

首先上执行流程图:

       第1步,浏览器发送请求URL,进入DispatcherServlet前端控制器,它本质上还是一个Servlet,通过源码看出继承关系:

DispatcherServlet  ----->FrameworkServlet----->HttpServletBean----->HttpServlet----->实现Servlet

进入DispatcherServlet源码,它可以调用doService()方法,这个是核心方法,其中里面又调用了doDispatch()方法其作用就是分发请求和响应

 


 

 

       我们进入doDispatch()方法源码,只看已经标红线的部分,可以看到mappedHandler是HandlerExecutionChain(处理器执行链)类型的数据,同时下面又调用了getHandler()方法得到了一个mappedHandler处理器执行链类型的数据对象,其实这一步就包含了上面流程图的第2,3步(注意getHandler()方法源码还在DispatcherServlet窗口中,所以用this.getHandler()调用)。

 

 

       第2,3步,我们直接进入getHandler()方法源码,发现有一个叫HandlerMappings的集合,它通过Iterator迭代器遍历了其中的HandlerMapping(处理器映射器),也就是根据用户的请求查找到了对应的处理器映射器(其实是BeanNameUrlHandlerMapping),然后调用方法返回数据类型是HandlerExecutionChain的对象。

 

      

       有人会问HandlerExecutionChain里到底有啥,查看源码发现,它就是封装了Handler(处理器,就是你自己写的类,加上@Controller,@RequestMapping等注解的代码类),以及包含HandlerInterceptor(处理器拦截器)的List数组

 

 

         第4步,回到DispatcherServlet源码下的doDispatch()方法中,我们往下看,有一个getHandlerAdapter()方法,返回的是一个HandlerAdapter(处理器适配器对象),我们注意到getHandlerAdapter()方法中的参数是mappedHandler.getHandler(),这时有人疑惑了,怎么处理器执行链也能调用getHandler()方法,不是只有处理器映射器才能调用并返回处理器执行链对象吗,其实是在HandlerExecutionChain(处理器执行链)中,也有一个getHandler()方法,它返回了一个Handler类型的对象。

 

 

 

 

       从这就能明白了:getHandlerAdapter()方法就是通过你写的Controller代码作为Handler对象传入方法中,获取相应的处理器适配器。那怎么获取处理器适配器对象呢,翻看getHandlerAdapter()方法源码发现它和上面找HandlerMapping(处理器映射器)类似,都是通过迭代器遍历集合,然后返回支持Handler对象的处理器适配器(一般是SimpleControllerHandlerAdapter)

 

 

        第5,6,7步,我们回到DispatcherServlet源码下的doDispatch()方法中,继续向下看,我们发现了一个handle()方法,它是处理器适配器ha调用handle()方法返回一个ModelAndView类型的对象mv,这就是第5,7步。

 

 

 

 

     

      我们继续深入查看一下handle()方法源码,Ctrl+B,发现直接跳转到了HandlerAdapter.class中,但是它是一个接口,因此我们要查看它的具体实现类中的handle()方法,再次Ctrl+Alt+B,进入SimpleControllerHandlerAdapter类中查看,发现有一个Object handler参数,这就是前面提到的自己写的Controller代码类,所以能强转为Controller对象,然后Controller接口有一个handleRequest()方法,Ctrl+B,发现也返回的是一个ModelAndView类型的对象,这是第6步。另外,注意还有applyPreHandle()和applyPostHandle()两个方法,他们是都是拦截器,在处理前拦截和在处理后拦截。

 

 

       第8,9,10步,我们回到DispatcherServlet源码下的doDispatch()方法中,继续向下看,有一个processDispatchResult()方法,表示处理分发的结果,把之前得到的参数全部传入,进入方法源码,我们只关注标红线的部分,因为这是核心。

 

 

 

 

 

      

       再进入render()方法中,发现定义了一个View视图对象,而且通过resolveViewName()和getView()返回了View对象,通过方法源码可知这其实就是调用了ViewResolver(视图解析器)返回了View。

 

 

 

    

       我们再接着往下看,发现View对象也调用了render(),Ctrl+b,进入VIew.class,是一个接口,我们继续找其实现类AbstractView,发现有一个renderMergedOutputModel()方法,其中的Output已经有着输出的意思了,代表第10,11步。

 

 

 

 

 

      

       我们继续深入找寻,发现它是一个抽象方法,找到具体实现类InternalResourceView其中的重写方法,发现里面通过调用方法获得了requestdispatch请求分发器,包含forward和include两种响应方式

 

 

 

 

 

 

 

posted @ 2022-05-07 21:13  学习没什么用  阅读(109)  评论(0)    收藏  举报