• Spring MVC源码分析(续)——请求处理


    转自:http://blog.csdn.net/shi1122/article/details/8041017

    (转移位置了,时光隧道:http://www.jmatrix.org/spring/501.html)      

            在之前的“spring MVC实现分析——初始化”中分析了spring mvc的初始化过程,接下来将分析其请求处理过程。

            在找请求处理的入口时,我们需要先知道Servlet的编程规范,对应不同的请求(如POST、GET等)的实现方法在FrameworkServlet 中,分别是doPost、doGet等,看这一系列方法的具体实现可以知道,请求的处理跳转到了processRequest函数中,最终进入 DispatcherServlet的doService函数,详细的流程如:



    上面的时序图展示了详细的请求处理流程,其中最重要的是doDispatch函数,其中包含了整个的处理逻辑,

    1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
    2.         HttpServletRequest processedRequest = request;  
    3.         HandlerExecutionChain mappedHandler = null;  
    4.         boolean multipartRequestParsed = false;  
    5.   
    6.         WebAsyncManager asyncManager = AsyncWebUtils.getAsyncManager(request);  
    7.   
    8.         try {  
    9.             ModelAndView mv = null;  
    10.             Exception dispatchException = null;  
    11.   
    12.             try {  
    13.                 processedRequest = checkMultipart(request);  
    14.                 multipartRequestParsed = processedRequest != request;  
    15.   
    16.                 // Determine handler for the current request.  
    17.                 mappedHandler = getHandler(processedRequest, false);  
    18.                 if (mappedHandler == null || mappedHandler.getHandler() == null) {  
    19.                     noHandlerFound(processedRequest, response);  
    20.                     return;  
    21.                 }  
    22.   
    23.                 // Determine handler adapter for the current request.  
    24.                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
    25.   
    26.                 // Process last-modified header, if supported by the handler.  
    27.                 ……  
    28.                 try {  
    29.                     // Actually invoke the handler.  
    30.                     mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
    31.                 }  
    32.                 finally {  
    33.                     if (asyncManager.isConcurrentHandlingStarted()) {  
    34.                         return;  
    35.                     }  
    36.                 }  
    37.   
    38.                 applyDefaultViewName(request, mv);  
    39.                 mappedHandler.applyPostHandle(processedRequest, response, mv);  
    40.             }  
    41.             catch (Exception ex) {  
    42.                 dispatchException = ex;  
    43.             }  
    44.             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  
    45.         }  
    46.         ……  
    47.         }  
    48.         finally {  
    49.             ……  
    50.         }  
    51.     }  

    首先我们先看HandlerExecutionChain这个类中有些什么东西,

    1. public class HandlerExecutionChain {  
    2.   
    3.     private final Object handler;  
    4.   
    5.     private HandlerInterceptor[] interceptors;  
    6.   
    7.     private List<HandlerInterceptor> interceptorList;  
    8.   
    9.     ……  
    10. }  

            这里面有两个关键的东西handler与interceptors,也即处理器对象与拦截器链表,联系到我们实际的编程,handler有可能是两种东 西:(1)controller类对象;(2)controller中的方法对象(用的术语可能不太准确……)。而interceptors也即我们定义 拦截器对象列表,如果说想在请求被处理之前做点什么就会弄一个。明白了这一点,再来看看在doDispatch函数中如果获得 HandlerExecutionChain对象mappedHandler。

            可以看到其实现在getHandler方法中:

    1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  
    2.         for (HandlerMapping hm : this.handlerMappings) {  
    3.             ……  
    4.             HandlerExecutionChain handler = hm.getHandler(request);  
    5.             if (handler != null) {  
    6.                 return handler;  
    7.             }  
    8.         }  
    9.         return null;  
    10.     }  

             函数的实现非常简单:遍历已注册的HandlerMapping列表,通过HandlerMapping对象的getHandler函数获取 HandlerExecutionChain对象。至于HandlerMapping中的getHandler函数如何获取 HandlerExecutionChain需要的处理器与拦截器,我只能说过程是繁琐的,原理是简单的,对于处理器对象(handler)根据不同的 Mapping实现,其可以根据bean配置中的urlPath或者是方法的注解来寻找,这里不再细说。

             顺着doDispatch函数的执行流程往下看,紧接着其通过getHandlerAdapter函数获得HandlerAdapter对象ha,然后就是又要重点照顾的一个调用:

    1. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  

             随着调用HandlerAdapter的handle函数,Spring MVC便开始要真的“干实事”了,所谓的“干实事”也即开始调用执行我们编写的controller(控制逻辑)了。这里以两个 HandlerAdapter的实现HttpRequestHandlerAdapter与 AnnotationMethodHandlerAdapter来分析这个处理流程,在之前的一篇文章“Spring MVC实现分析——初始化过程”中有提到我自己的一个Spring MVC程序配置,以此为准进行展开:

             HttpRequestHandlerAdapter的实现是最容易理解的,因为其handle的实现就是调用了处理器(handler)对象的 handleRequest函数,借助F4看看Controller的继承体系,再看看AbstractController中 handleRequest函数的实现,结合自己菜鸟时期编写的Spring MVC “hello world程序”,你就会有恍然大悟的感觉⊙﹏⊙!

             至于AnnotationMethodHandlerAdapter,其实现原理也是很容易理解的,我们已经知道其就是针对采用注解方式的方法映射的,实际应用中如:

    1. @RequestMapping(method=RequestMethod.GET,value="/homeController.xhtml")  
    2.     protected ModelAndView handleRequestInternal(HttpServletRequest arg0,  
    3.             HttpServletResponse arg1) throws Exception {  
    4.       ……  
    5. }  

            所以其handle的实现就是通过Java的反射机制找到注解对应的处理方法,并调用完成控制逻辑的执行。

            此时,让我们再次回到doDispatch的处理流程上来,在经过handle的“干实事”后,我们得到了ModelAndView对象,也即视图对象, 很自然接下来的就是视图的渲染与展示了,这也是我们最后要分析的一个点。其入口是doDispatch中的一个函数调用:

      1. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 
  • 相关阅读:
    桐花万里python路-基础篇-01-历史及进制
    linux-tar归档文件
    python-常识
    目录权限修改
    linux常用命令
    battery-historian 使用方法
    cp --复制命令
    adb与bat混用启动与杀死应用程序
    monkey 命令
    INSERT INTO SELECT 语句
  • 原文地址:https://www.cnblogs.com/20000ding/p/5421165.html
Copyright © 2020-2023  润新知