当前位置:   article > 正文

SpringMVC源码流程(一)_springmvc执行的源码入口

springmvc执行的源码入口

目录

一、先来看SpringMVC的初始化(前奏)

1、SpringMVC的九大组件:

2、对于九大组件,前端控制器DispatcherServlet会进行初始化

        二、SpringMVC执行流程

1)找到源码入口

2)进入到DispatcherServlet的doDispatch()

3)各方法的具体实现细节

①getHandler()获取处理器

②getHandlerAdapter()获取适配器

③执行目标方法的细节;


一、先来看SpringMVC的初始化(前奏)

1、SpringMVC的九大组件:

(这是mvc核心的部分,后面的mvc的流程以及其他功能都需要依靠这九大组件)

multipartResolver:文件上传解析器

localeResolver:区域信息解析器,和国际化有关

themeResolver:主题解析器

handlerMappings:handler的映射器

handlerAdapters:handler的适配器

handlerExceptionResolvers:异常解析功能

viewNameTranslator:请求到视图名的转换器

flashMapManager:SpringMVC中允许重定向携带数据的功能

viewResolvers:视图解析器

2、对于九大组件,前端控制器DispatcherServlet会进行初始化

DispatcherServlet中:onRefresh()->initStrategies()
 
  1. protected void initStrategies(ApplicationContext context) {
  2.         initMultipartResolver(context);
  3.         initLocaleResolver(context);
  4.         initThemeResolver(context);
  5.         initHandlerMappings(context);
  6.         initHandlerAdapters(context);
  7.         initHandlerExceptionResolvers(context);
  8.         initRequestToViewNameTranslator(context);
  9.         initViewResolvers(context);
  10.         initFlashMapManager(context);
  11.     }

例如:初始化HandlerMapping(后面需要用到,先了解知道一下就可以哦)

  1. private void initHandlerMappings(ApplicationContext context) {
  2.         this.handlerMappings = null;
  3.         if (this.detectAllHandlerMappings) {
  4.             // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
  5.             Map<String, HandlerMapping> matchingBeans =
  6.                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
  7.             if (!matchingBeans.isEmpty()) {
  8.                 this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
  9.                 // We keep HandlerMappings in sorted order.
  10.                 OrderComparator.sort(this.handlerMappings);
  11.             }
  12.         }
  13.         else {
  14.             try {
  15.                 HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
  16.                 this.handlerMappings = Collections.singletonList(hm);
  17.             }
  18.             catch (NoSuchBeanDefinitionException ex) {
  19.                 // Ignore, we'll add a default HandlerMapping later.
  20.             }
  21.         }
  22.         // Ensure we have at least one HandlerMapping, by registering
  23.         // a default HandlerMapping if no other mappings are found.
  24.         if (this.handlerMappings == null) {
  25.             this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
  26.             if (logger.isDebugEnabled()) {
  27.                 logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
  28.             }
  29.         }
  30.     }

***********关键点来喽~~~

组件的初始化: 有些组件初始化在容器中是使用类型找的,有些组件是使用id找的;
去容器中找这个组件,如果没有找到就用默认的配置;
注意点:如果后面需要自己实现的组件需要在ioc容器中注册,而注册的时候有些组件就需要专门指定的id才可以去注入成功(否则注入不上的)

二、SpringMVC执行流程

1)找到源码入口

  1. 当客户端发送请求时,会被tomcat拦截,进入到doGet或者doPost的方法中去
  2. 根据继承关系,FrameworkServlet会将基类的HttpServlet的doGet和doPost重写,并且调用doService()
  3. 前端控制器DispatcherServlet继承FrameworkServlet后重写了doService()方法,经过调用,进入到doDispatch()经过这么一些曲折的寻找,最后终于可以根据源码来探究mvc的流程了

2)进入到DispatcherServlet的doDispatch()

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        try {
            ModelAndView mv = null;
            Exception dispatchException = null;
            try {
                
                 //1、检查是否文件上传请求
                processedRequest = checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                
                // Determine handler for the current request.
                 //2、根据当前的请求地址找到那个类能来处理;
                mappedHandler = getHandler(processedRequest);
 
 
                 //3、如果没有找到哪个处理器(控制器)能处理这个请求就404,或者抛异常
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }
 
 
                // Determine handler adapter for the current request.
                 //4、拿到能执行这个类的所有方法的适配器;(反射工AnnotationMethodHandlerAdapter)
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
                
                // Process last-modified header, if supported by the handler.
                
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
                try {
                    
                    // Actually invoke the handler.处理(控制)器的方法被调用
                    //控制器(Controller),处理器(Handler)
                     //5、适配器来执行目标方法;
                     //将目标方法执行完成后的返回值作为视图名,设置保存到ModelAndView中
                    //目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装成ModelAndView
                    
                    mv = ha.handle(processedRequest,response,mappedHandler.getHandler());
                } finally {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
                }
                applyDefaultViewName(request, mv);//如果没有视图名设置一个默认的视图名;
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception ex) {
                dispatchException = ex;
            }
            
             //转发到目标页面;
            //6、根据方法最终执行完成后封装的ModelAndView;
            //转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        } catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        } catch (Error err) {
            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                
                // Instead of postHandle and afterCompletion
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                return;
            }
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }

******由此,可以总结为如下几个大概方面

  1. 1.用户发出请求,DispatcherServlet接收请求并拦截请求。
  2. 2.调用doDispatch()方法进行处理:
  3. 1. getHandler():根据当前请求地址中找到能处理这个请求的目标处理器类(处理器);
  4. 1.根据当前请求在HandlerMapping中找到这个请求的映射信息,获取到目标处理器类
  5. 2. mappedHandler = getHandler(processedRequest);
  6. 2. getHandlerAdapter():根据当前处理器类找到能执行这个处理器方法的适配器;
  7. 1.根据当前处理器类,找到当前类的HandlerAdapter (适配器)
  8. 2. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler();
  9. 3.使用刚才获取到的适配器(AnnotationMethodHandlerAdapter)执行目标方法;
  10. mv = ha.handle(processedRequest,response,mappedHandler.getHandler());
  11. 4.目标方法执行后,会返回-个ModerAndView对象
  12. mv = ha.handle(processedRequest,response,mappedHandler.getHandler();
  13. 5.根据ModerAndView的信息转发到具体页面,并可以在请求域中取出ModerAndView中的模型数据
  14. processDispatchResult(processedRequest, response, mappedHandler, mv,dispatchException);

根据前面的doDispatch(),有两个组件我们需要使用到,那么再来强调一下这两个组件是干嘛的呢?

  1. HandlerMapping为处理器映射器,保存了每一个处理器能处理哪些请求的映射信息,handlerMap
  2. HandlerAdapter为处理器适配器,能解析注解方法的适配器,其按照特定的规则去执行Handler
 

3)各方法的具体实现细节

①getHandler()获取处理器

     **怎么根据当前请求就能找到哪个类能来处理?**
  • getHandler()会返回目标处理器类的执行链
  • HandlerMapping:处理器映射:他里面保存了每一个处理器能处理哪些请求的映射信息
  • handlerMap:ioc容器启动创建Controller对象的时候扫描每个处理器都能处理什么请求,保存在HandlerMapping的handlerMap属性中;下一次请求过来,就来看哪个HandlerMapping中有这个请求映射信息就行
循环遍历拿到能处理url的类
 
  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  2.         for (HandlerMapping hm : this.handlerMappings) {
  3.             if (logger.isTraceEnabled()) {
  4.                 logger.trace(
  5.                         "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
  6.             }
  7.             HandlerExecutionChain handler = hm.getHandler(request);
  8.             if (handler != null) {
  9.                 return handler;
  10.             }
  11.         }
  12.         return null;
  13.     }

注意点:遍历循环的this.handlerMappings里面在初始化前端控制器的时候就有东西了,有指定的处理器能处理就拿到该处理器,并直接返回。

②getHandlerAdapter()获取适配器

拿到适配器,通过适配器来调用目标方法

  1. protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
  2.         for (HandlerAdapter ha : this.handlerAdapters) {
  3.             if (logger.isTraceEnabled()) {
  4.                 logger.trace("Testing handler adapter [" + ha + "]");
  5.             }
  6.             if (ha.supports(handler)) {
  7.                 return ha;
  8.             }
  9.         }
  10.         throw new ServletException("No adapter for handler [" + handler +
  11.                 "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
  12.     }
RequestMappingHandlerAdapter适配器:
  • 能解析注解方法的适配器;

  • 处理器类中只要有标了注解的这些方法就能用;

③执行目标方法的细节;

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
          //拿到方法的解析器
        ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
           //方法解析器根据当前请求地址找到真正的目标方法
        Method handlerMethod = methodResolver.resolveHandlerMethod(request);
           //创建一个方法执行器;
        ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);
           //包装原生的request, response,
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
           //创建了一个,隐含模型
        ExtendedModelMap implicitModel = new BindingAwareModelMap() ;//**重点
 
 
         //真正执行目标方法;目标方法利用反射执行期间确定参数值,提前执行modelattribute等所有的操作都在这个方法中;
        Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
      
        ModelAndView mav = methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
    
        methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
    
        return mav;
    }

接下来深入到执行目标方法,来看看他们是如何执行的吧

Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);

publicfinal Object invokeHandlerMethod (Method handlerMethod, Object handler,
            NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
        Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
        try {
            boolean debug = logger.isDebugEnabled();
            for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
                Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
                if (attrValue != null) {
                    implicitModel.addAttribute(attrName, attrValue);
                }
            }
               
          //找到所有@ModelAttribute注解标注的方法;
            for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
                Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
                //先确定modelattribute方法执行时要使用的每一个参数的值;
               Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
                if (debug) {
                    logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
                }
                String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
                
                if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
                    continue;
                }
                
                ReflectionUtils.makeAccessible(attributeMethodToInvoke);
               
               //提前运行ModelAttribute
                Object attrValue = attributeMethodToInvoke.invoke(handler, args);
                if ("".equals(attrName)) {
                    Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
                    attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
                }
              
                //把提前运行的ModelAttribute方法的返回值也放在隐含模型中
                if (!implicitModel.containsAttribute(attrName)) {
                    implicitModel.addAttribute(attrName, attrValue);
                }
            }
 
 
               //再次解析目标方法参数是哪些值
             Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
            if (debug) {
                logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
            }
            ReflectionUtils.makeAccessible(handlerMethodToInvoke);
 
 
            
            //执行目标方法
            return handlerMethodToInvoke.invoke(handler, args);
        }
        catch (IllegalStateException ex) {
            // Internal assertion failed (e.g. invalid signature):
            // throw exception with full handler method context...
            throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
        }
        catch (InvocationTargetException ex) {
            // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
            ReflectionUtils.rethrowException(ex.getTargetException());
            return null;
        }
    }
对于前期的框架,相信大家应该有了一个框图,知道大概的流程模样。
接下来,对于到底具体如何执行目标方法的呢,请看SpringMVC流程(二)
 
 
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/1015664
推荐阅读
相关标签
  

闽ICP备14008679号