zoukankan      html  css  js  c++  java
  • SpringMVC源码执行流程

    1. Dispatcher核心执行方法: 

     

    2.doDispatcher详细细节:

      1)、所有请求过来,Dispatcher收到请求;

      2)、调用doDispatcher()方法进行处理;

        》1.getHandler():根据当前请求地址找到能处理这个请求目标处理器类  

            根据当前请求在HandlerMapping找到那个请求的映射信息,获取到目标处理器类

        》2.getHandlerAdapter():根据当前处理器类获取到能够执行这个处理器类的适配器;

            根据当前的处理器类,找到当前类的适配器(HandlerAdapter)

        》3.使用刚才获取到的适配器执行目标方法;

        》4.目标方法执行完后会返回一个ModelAndView对象;

        》5.将ModelAndView的信息转发到具体的页面,然后在请求域中取出ModelAndView中的模型数据;

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;
        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
        try {
            try {
                ModelAndView mv = null;
                Object dispatchException = null;
    
                try {
              //1.检查是否为文件上传请求 processedRequest
    = this.checkMultipart(request); multipartRequestParsed = processedRequest != request;
              //2.根据当前的请求地址找到哪个类能来处理 mappedHandler
    = this.getHandler(processedRequest);
              //3.如果没有找到对应的处理器(控制器)来处理这个请求,就报404或抛异常
    if (mappedHandler == null) { this.noHandlerFound(processedRequest, response); return; }           //4.拿到能执行这个类所有方法的适配器(反射工具);
      HandlerAdapter ha
    = this.getHandlerAdapter(mappedHandler.getHandler()); String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                
    if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { return; } } if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }           //处理器方法被调用;控制器(Controller)、处理器(Handler)
              //5.适配器来执行目标方法,将目标方法执行完成后的返回值作为视图名,设置保存到ModelAndView中
              //目标方法无论怎么写,最终适配器执行完成以后都会将执行后的信息封装到ModelAndView
    mv
    = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; }           //6.如果没有视图名,设置一个默认的视图名 this.applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var20) { dispatchException = var20; } catch (Throwable var21) { dispatchException = new NestedServletException("Handler dispatch failed", var21); }        //转发到目标页面
           //7.根据方法最终执行完成后封装的ModelAndView,转发到对应页面,而且ModelAndView中的数据可以从请求域中获取
    this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); } catch (Exception var22) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22); } catch (Throwable var23) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23)); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if (multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }

    3、getHandler()细节:怎么根据当前请求找到那个类来处理  

      》1.getHandler()会返回目标处理器类的执行链;

    mappedHandler = this.getHandler(processedRequest);

      》2.HandlerMapping:处理器映射,HandlerMappings里面保存了每一个处理器能处理哪些方法的映射信息;

    
    
    @Nullable
    private List<HandlerMapping> handlerMappings;
    @Nullable
        protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            if (this.handlerMappings != null) {
                Iterator var2 = this.handlerMappings.iterator();
                while(var2.hasNext()) {
                    HandlerMapping mapping = (HandlerMapping)var2.next();
                    HandlerExecutionChain handler = mapping.getHandler(request);
                    if (handler != null) {
                        return handler;
                    }
                }
            }
            return null;
        }

    4、如何找到目标处理器类 额适配器,要拿适配器去执行目标方法

        protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
            if (this.handlerAdapters != null) {
                Iterator var2 = this.handlerAdapters.iterator();
    
                while(var2.hasNext()) {
                    HandlerAdapter adapter = (HandlerAdapter)var2.next();
                    if (adapter.supports(handler)) {
                        return adapter;
                    }
                }
            }
    
            throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
        }

    5、DispatcherServlet中有几个引用类型的属性:

      SpringMVC的九大组件:

               SpringMVC在工作的时候,关键位置都是由这些组件完成的;共同点:九大组件全部是接口,接口就是规范,提供了非常强大的扩展性;

        /** 文件上传解析器 */
        private MultipartResolver multipartResolver;
    /** 区域解析器和国际化有关 */
    private LocaleResolver localeResolver;
    /** 主题解析器;强大的主题效果切换 */
    private ThemeResolver themeResolver;
    /** handler映射信息;HandlerMapping */
    private List<HandlerMapping> handlerMappings;
    /** handler适配器 */
    private List<HandlerAdapter> handlerAdapters;
    /** SpringMVC强大的异常解析功能:异常解析器 */
    private List<HandlerExceptionResolver> handlerExceptionResolvers;
    /** 请求到视图名转换器 */
    private RequestToViewNameTranslator viewNameTranslator;
    /** FlsahMap+Manager:SpringMVC中进行重定向携带数据的功能 */
    private FlashMapManager flashMapManager;
    /** 视图解析器 */
    private List<ViewResolver> viewResolvers;

      DispatcherServlet中九大组件初始化的地方:服务器启动就初始化

        组件的初始化:

          去容器中找这个组件,如果没有找到就用默认配置;有些组件是用类型找的,有些组件使用bean-id找的;

        protected void initStrategies(ApplicationContext context) {
            this.initMultipartResolver(context);
            this.initLocaleResolver(context);
            this.initThemeResolver(context);
            this.initHandlerMappings(context);
            this.initHandlerAdapters(context);
            this.initHandlerExceptionResolvers(context);
            this.initRequestToViewNameTranslator(context);
            this.initViewResolvers(context);
            this.initFlashMapManager(context);
        }

      

  • 相关阅读:
    Java Number类
    Java StringBuffer和StringBuilder类
    Java String类
    Java 日期时间
    Java 数组
    Java 方法
    Java正则表达式
    一步步学习SPD2010--第五章节--处理数据视图(6)--使用XSLT
    一步步学习SPD2010--第五章节--处理数据视图(5)--显示和隐藏内容
    一步步学习SPD2010--第五章节--处理数据视图(4)--应用条件格式
  • 原文地址:https://www.cnblogs.com/luliang888/p/11073498.html
Copyright © 2011-2022 走看看