zoukankan      html  css  js  c++  java
  • springMvc之doDispatch

    上一篇总结了SpringMvc的前端控制器DispatcherServlet整体的初始话过程,最终分析到DispatcherServlet.doDispatch()方法,本篇就是主要分析SpringMvc的核心,doDispatch()方法处理请求的整体流程。

    doDispatch方法整体源码:

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
       HttpServletRequest processedRequest = request;
      //HandlerExecutionChain(处理器执行链)保存需要执行的处理器和拦截器
       HandlerExecutionChain mappedHandler = null;
       boolean multipartRequestParsed = false;
       //异步请求管理器
       WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
       try {
          ModelAndView mv = null;
          Exception dispatchException = null;
    
          try {
            //检查是否为Multipart请求,如果是则返回的是一个MultipartHttpServletRequest类型的request,不是则返回原来的request
             processedRequest = checkMultipart(request);
            //根据返回是否原来的对象来判断,request是否已经被处理过
             multipartRequestParsed = (processedRequest != request);
    
             //根据uri找到HandlerExecutionChain(包含了我们写的处理器和拦截器)
             mappedHandler = getHandler(processedRequest);
             if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
             }
    
             //获取到处理器适配器,用于执行HandlerExecutionChain
             HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
             //处理last-modified缓存机制,处理器支持需要实现LastModified接口
             String method = request.getMethod();
             boolean isGet = "GET".equals(method);
             //last-modified 只支持get或者HEAD请求
             if (isGet || "HEAD".equals(method)) {
               //上次修改资源的时间
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (logger.isDebugEnabled()) {
                   logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                }
               //修改时间与上次请求的时间一致,那么表示资源未改变,直接返回304状态码,浏览器使用上次缓存结果
                if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                   return;
                }
             }
    			//执行mappedHandler中所有HandlerInterceptor(拦截器)applyPreHandle方法
             if (!mappedHandler.applyPreHandle(processedRequest, response)) {
               //如果有applyPreHandle返回的是false,则结束doDispatch方法的执行
                return;
             }
    
             // 执行处理器方法,返回ModelAndView
             mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    		//如果本次是异步请求,直接退出doDispatch方法的执行
             if (asyncManager.isConcurrentHandlingStarted()) {
                return;
             }
    		//如果返回的ModelAndView中的ViewName为空时,设置一个默认的ViewName
             applyDefaultViewName(processedRequest, mv);
            //执行mappedHandler中所有HandlerInterceptor(拦截器)applyPostHandle方法
             mappedHandler.applyPostHandle(processedRequest, response, mv);
          }
          catch (Exception ex) {
            //保存异常,用于后面的@ExceptionHandler方法处理
             dispatchException = ex;
          }
          catch (Throwable err) {
             // As of 4.3, we're processing Errors thrown from handler methods as well,
             // making them available for @ExceptionHandler methods and other scenarios.
             //保存错误,用于后面的@ExceptionHandler方法处理
             dispatchException = new NestedServletException("Handler dispatch failed", err);
          }
         //处理结果并响应浏览器
          processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
       }
      
       catch (Exception ex) {
         //异常时,也会执行mappedHandler中所有HandlerInterceptor(拦截器)AfterCompletion方法
          triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
       }
       catch (Throwable err) {
         //错误时,也会执行mappedHandler中所有HandlerInterceptor(拦截器)AfterCompletion方法
          triggerAfterCompletion(processedRequest, response, mappedHandler,
                new NestedServletException("Handler processing failed", err));
       }
       finally {
          if (asyncManager.isConcurrentHandlingStarted()) {
             //如果是异步请求,执行mappedHandler中所有AsyncHandlerInterceptor(异步拦截器)的afterConcurrentHandlingStarted方法
             if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
             }
          }
          else {
             // 关闭Multipart请求的相关资源
             if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
             }
          }
       }
    }
    

    接下来具体分析几个重要步骤:

    [TOC]
    1)getHandler(processedRequest):找到需要执行的处理器执行链(HandlerExecutionChain)
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
      //遍历每一个HandlerMapping执行getHandler方法,直到获取到一个HandlerExecutionChain,并返回
       for (HandlerMapping hm : this.handlerMappings) {
          if (logger.isTraceEnabled()) {
             logger.trace(
                   "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
          }
          HandlerExecutionChain handler = hm.getHandler(request);
          if (handler != null) {
             return handler;
          }
       }
       return null;
    }
    

    ​ DispatcherServlet.properties中默认配置的HandlerMapping:

    ​ org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping:根据Controller在ioc容器中的name或者alias(别名)查找

    ​ org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping(已过时)

    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter(代替DefaultAnnotationHandlerMapping: 用于查找标注了@RequestMapping等注解的处理器,最常用

    2)getHandlerAdapter(mappedHandler.getHandler())找到支持的对应处理器的处理器适配器一般现在都是用RequestMappingHandlerAdapter:
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
      //遍历所有的HandlerAdapter,执行supports来找到支持的对应处理器的处理器适配器
       for (HandlerAdapter ha : this.handlerAdapters) {
          if (logger.isTraceEnabled()) {
             logger.trace("Testing handler adapter [" + ha + "]");
          }
          if (ha.supports(handler)) {
             return ha;
          }
       }
       throw new ServletException("No adapter for handler [" + handler +
             "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }
    

    DispatcherServlet.properties中默认配置的HandlerAdapter:

    ​ org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter:用来执行实现了RequestHandler接口的Controller

    ​ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter:用来执行实现了Controller接口的Controller

    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter(已过时)

    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping(代替AnnotationMethodHandlerAdapter):执行标注了@RequestMapping等注解的处理器,最常用

    3)mappedHandler.applyPreHandle(processedRequest, response)执行HandlerExecutionChain中所有拦截器的applyPreHandle(processedRequest, response)方法
    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
      	//遍历执行Interceptor.preHandle
       HandlerInterceptor[] interceptors = getInterceptors();
       if (!ObjectUtils.isEmpty(interceptors)) {
          for (int i = 0; i < interceptors.length; i++) {
             HandlerInterceptor interceptor = interceptors[i];
            //preHandle(request, response, this.handler)返回false,则triggerAfterCompletion(request, response, null),并不再执行接下来的其他处理器的preHandle
             if (!interceptor.preHandle(request, response, this.handler)) {
                triggerAfterCompletion(request, response, null);
                return false;
             }
            //保存最后一个preHandle(request, response, this.handler)返回true的拦截器索引值
             this.interceptorIndex = i;
          }
       }
       return true;
    }
    
    4)triggerAfterCompletion(request, response, null):如果存在拦截器的applyPreHandle方法返回false,则触发执行拦截器的afterCompletion方法:
    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
          throws Exception {
       HandlerInterceptor[] interceptors = getInterceptors();
       if (!ObjectUtils.isEmpty(interceptors)) {
         //逆序执行上一步preHandle(request, response, this.handler)返回true的拦截器的afterCompletion方法
          for (int i = this.interceptorIndex; i >= 0; i--) {
             HandlerInterceptor interceptor = interceptors[i];
             try {
                interceptor.afterCompletion(request, response, this.handler, ex);
             }
             catch (Throwable ex2) {
                logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
             }
          }
       }
    }
    
    5)ha.handle(processedRequest, response, mappedHandler.getHandler())使用处理器适配器执行处理器方法:
    @Override//handlerMethod保存了处理器对象和当前需要执行的处理器方法等信息
    protected ModelAndView handleInternal(HttpServletRequest request,
          HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
       ModelAndView mav;
       checkRequest(request);
    
       // this.synchronizeOnSession 默认为false,对于同一个session的request,是否同步执行处理器方法.
       if (this.synchronizeOnSession) {
          HttpSession session = request.getSession(false);
          if (session != null) {
             Object mutex = WebUtils.getSessionMutex(session);
             synchronized (mutex) {
                mav = invokeHandlerMethod(request, response, handlerMethod);
             }
          }
          else {
             // No HttpSession available -> no mutex necessary
             mav = invokeHandlerMethod(request, response, handlerMethod);
          }
       }
       else {
          //执行处理器方法
          mav = invokeHandlerMethod(request, response, handlerMethod);
       }
    
       if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
          if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
             applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
          }
          else {
             prepareResponse(response);
          }
       }
    
       return mav;
    }
    

    直接看invokeHandlerMethod(request, response, handler):

    protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
    			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
    
    		ServletWebRequest webRequest = new ServletWebRequest(request, response);
    		try {
              	//查找处理器中标注了@InitBinder的方法及相应的@ControllerAdvice类,保存在binderFactory
    			WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
              	//查找处理器中标注了@ModelAttribute的方法及相应的@ControllerAdvice类,保存在modelFactory中
    			ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
    			//ServletInvocableHandlerMethod:可执行的处理器方法
    			ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
              	//设置处理器方法参数解析器
    			invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
              	//处理器方法返回值的处理器
    			invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
    			invocableMethod.setDataBinderFactory(binderFactory);
              	//参数名称发现器
    			invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
    			//mavContainer用于存放所有可能会用到的ModelAndView
    			ModelAndViewContainer mavContainer = new ModelAndViewContainer();
              	//添加重定向参数
    			mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
              	//初始化model,就是填充model,添加Sesson中的参数名与处理器方法参数一致的参数,执行@ModelAttribute标注的处理器方法
    			modelFactory.initModel(webRequest, mavContainer, invocableMethod);
    			mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
    			//下面是异步请求相关
    			AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);  //设置异步执行,超时时间
    			asyncWebRequest.setTimeout(this.asyncRequestTimeout);
    			//异步管理器
    			WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
              	//设置异步执行器
    			asyncManager.setTaskExecutor(this.taskExecutor);
              	//设置异步请求
    			asyncManager.setAsyncWebRequest(asyncWebRequest);
              	//注册返回值为Callable的异步拦截器
    			asyncManager.registerCallableInterceptors(this.callableInterceptors);
              	//注册返回值为DeferredResult的异步拦截器
    			asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
    			//如果本次请求时异步请求的转发
    			if (asyncManager.hasConcurrentResult()) {
    				Object result = asyncManager.getConcurrentResult();
    				mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
    				asyncManager.clearConcurrentResult();
    				if (logger.isDebugEnabled()) {
    					logger.debug("Found concurrent result value [" + result + "]");
    				}
    				invocableMethod = invocableMethod.wrapConcurrentResult(result);
    			}
    			//执行处理器:大概步骤:解析处理器方法参数 反射调用处理器方法 解析返回值等操作
    			invocableMethod.invokeAndHandle(webRequest, mavContainer);
    			if (asyncManager.isConcurrentHandlingStarted()) {
    				return null;
    			}
    			//返回ModelAndView对象
    			return getModelAndView(mavContainer, modelFactory, webRequest);
    		}
    		finally {
    			webRequest.requestCompleted();
    		}
    	}
    
    6)mappedHandler.applyPostHandle(processedRequest, response, mv):执行拦截器的postHandle方法
    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
    	HandlerInterceptor[] interceptors = getInterceptors();
    	if (!ObjectUtils.isEmpty(interceptors)) {
           //逆序执行
    		for (int i = interceptors.length - 1; i >= 0; i--) {
    			HandlerInterceptor interceptor = interceptors[i];
    			interceptor.postHandle(request, response, this.handler, mv);
    		}
    	}
    }
    
    7)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException):处理结果并响应给浏览器
    //exception 执行处理器方法报错时被捕获的异常
    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
          HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
    
       boolean errorView = false;
    	//如果存在异常
       if (exception != null) {
          if (exception instanceof ModelAndViewDefiningException) {
             logger.debug("ModelAndViewDefiningException encountered", exception);
             mv = ((ModelAndViewDefiningException) exception).getModelAndView();
          }
          else {
             Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            //处理异常,执行自定义异常处理方法即被@ExceptionHandler标注,并返回一个ModelAndView
             mv = processHandlerException(request, response, handler, exception);
             errorView = (mv != null);
          }
       }
    
       //如果mv不为空,且没有被清理,也就是请求在此之前还没有响应浏览器
       if (mv != null && !mv.wasCleared()) {
         //使用视图解析器获取视图对象,渲染视图,响应浏览器
          render(mv, request, response);
          if (errorView) {
             WebUtils.clearErrorRequestAttributes(request);
          }
       }
       else {
          if (logger.isDebugEnabled()) {
             logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                   "': assuming HandlerAdapter completed request handling");
          }
       }
    
       if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
          // Concurrent handling started during a forward
          return;
       }
    
       if (mappedHandler != null) {
          //执行所有拦截器的AfterCompletion方法
          mappedHandler.triggerAfterCompletion(request, response, null);
       }
    }
    

    结束。。。

  • 相关阅读:
    css3--简单的加载动画
    background--详解(背景图片根据屏幕的自适应)
    css--两行显示省略号兼容火狐浏览器
    tortoisegit--无法commit
    vim--学习
    JavaScript--数据结构与算法之图
    JSONP
    数据结构--只用位运算实现加减乘除操作
    剑指offer——不用加减乘除做加法
    shop--10.前端展示系统--首页展示(后台)
  • 原文地址:https://www.cnblogs.com/qzlcl/p/11204372.html
Copyright © 2011-2022 走看看