VVL1295

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  其实全过程分析就是主要分析 DispatcherServlet 的 doDispatch() 方法,本文基于 Spring 4.0.4。

  1,判断是否为 Multipart 类型的请求:

//org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
processedRequest = checkMultipart(request);

  如果是 multipart 类型的请求,就返回一个 request wrapper,否则返回作为入参的 request;

 

  2,获取合适的 HandlerExecutionChain 对象:

//org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
mappedHandler = getHandler(processedRequest);
   //org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest request)
   /** * Return the HandlerExecutionChain for this request. * <p>Tries all handler mappings in order. * @param request current HTTP request * @return the HandlerExecutionChain, or {@code null} if no handler could be found */ protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 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; }

  过程为,获取注册的 HandlerMapping,然后通过 HandlerMapping 对象获取 HandlerExecutionChain 对象,里面包含 Handler 对象和若干个 Interceptor,过程是通过 URL 获取映射的 Handler;

 

  3,判断是否有映射的 Handler:


//org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
if
(mappedHandler == null || mappedHandler.getHandler() == null) {
  noHandlerFound(processedRequest, response);
return; }
    
  //org.springframework.web.servlet.DispatcherServlet.noHandlerFound(HttpServletRequest request, HttpServletResponse response)
  /** * No handler found -> set appropriate HTTP response status. * @param request current HTTP request * @param response current HTTP response * @throws Exception if preparing the response failed */ protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws Exception { if (pageNotFoundLogger.isWarnEnabled()) { pageNotFoundLogger.warn("No mapping found for HTTP request with URI [" + getRequestUri(request) + "] in DispatcherServlet with name '" + getServletName() + "'"); } if (this.throwExceptionIfNoHandlerFound) { ServletServerHttpRequest sshr = new ServletServerHttpRequest(request); throw new NoHandlerFoundException( sshr.getMethod().name(), sshr.getServletRequest().getRequestURI(), sshr.getHeaders()); } else { response.sendError(HttpServletResponse.SC_NOT_FOUND);//404 } }

  没有则返回 404;

 

  4,获取 HandlerAdapter

//org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

  获取适合的 HandlerAdapter;

 

  5,预处理(待定):

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}

  

  6,真正进行功能处理(代码很多,流程会尽量叙述完整,但只会贴出较为重要的代码,这个过程也是最需要了解的过程):

    1,判断是否有 @SessionAttribute,有的话,进行检查和准备:

     //org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.getLastModifiedInternal(HttpServletRequest, HandlerMethod)
     if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { // Always prevent caching in case of session attribute management. checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true); }

    2,真真正正进行处理功能处理方法,到了 RequestMappingHandlerAdapter 的 invokeHandleMethod:

      1,createRequestMappingMethod,获取映射的方法;

      2,加入 FlashMap (待定);

      3,initModel:

        1,retriveAttribute: 在 session 里面寻找 @SessionAttribute 里的属性名对应的 属性,把属性放进 model 里面;

        2,invokeModelAttributeMethods:以下的model都为mavContainer里的model,调用全部 @ModelAttribute 修饰的方法:如果 model 里面已经含有 @ModelAttribute 里面的属性的属性名,则不执行该方法,反之,执行该方法;

          里面有个方法 invokeForRequest(org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(NativeWebRequest, ModelAndViewContainer, Object...)) ,resolveArgument,选取 resolver 时,如果是 Servlet API 的参数,会使用相应的 resolver(ServletRequestMethodArgumentResolver),如果是其他的参数,会使用相应的 resolver;

          如果是其他的没有用注解的参数,会使用ServletModelAttributeMethodProcessor 处理功能方法参数,如果model存在同名的属性,就把model里的属性重新绑定,不存在,就创建一个attribute,再进行绑定,绑定的具体做法是先匹配URI模型变量参数,匹配不上再匹配请求参数,再匹配不上就实例化一个 WebDataBinder对象进行匹配(具体的做法是把与类的属性名匹配的请求参数,赋值给参数),然后再把属性放进model 里面;

          如果是注解的参数,待定。

        3,findSessionAttributeArguments:找到handlerMethod 里的全部被 @ModelAttribute 修饰的且是SessionAttribute的参数,如果该值为 null,则抛出异常,Expected session attribute...,即在执行功能处理方法之前,必须已对 session

attribute 赋值;

      4,处理taskExecutor,asyncWebRequest,intercepteptor,redirect,timeout;

      5,invokeAndHandle,同样需要invokeForRequest(org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(NativeWebRequest, ModelAndViewContainer, Object...)),同上;

posted on 2016-09-02 11:45  bobo2018  阅读(230)  评论(0)    收藏  举报