spring源码---mvc:处理流程

请求处理流程:

从jdk的HttpServlet到达DispatcherServlet类的doDIspatch()方法的过程如下:

具体的代码可以参考:https://blog.csdn.net/zknxx/article/details/75194820

现在我们从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);
         //2.取得处理当前请求的Controller,也就是Handler 【★】
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) { //如果为空,直接返回404
            noHandlerFound(processedRequest, response);
            return;
         }
         //3.获取处理请求的处理器适配器 HandlerAdapter
         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
         //处理 last-modified请求头
         String method = request.getMethod();
         boolean isGet = "GET".equals(method);
        if (!mappedHandler.applyPreHandle(processedRequest, response)) { //4.调用执行器链中的拦截器
           return;
         }
         //5. 实际处理器处理请求,返回结果视图对象 【★】
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
         //结果视图对象的处理
         applyDefaultViewName(processedRequest, mv);
         mappedHandler.applyPostHandle(processedRequest, response, mv);
      }
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
}

1.checkMultipart()

 检查他是否是上传请求:

protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
   if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
      if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
      }
      else if (hasMultipartException(request)) {
      }
      else {
         try {
            return this.multipartResolver.resolveMultipart(request); //【调用解析】
         }
   }
   return request;
}

    该代码检查请求是否上传了文件,如果没有直接返回原始请求,如果具有请求文件,那么需要调用解析器,进行解析,这里存在两个安全判断,一个是解析器是否为空,解析器必须我们手动配置一个实现类,解析类比如:CommonsMultipartResolver类的解析方法:

public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException {
   Assert.notNull(request, "Request must not be null");
   if (this.resolveLazily) { //是不是延迟解析文件,默认是false
      //产生一个新的request请求
      return new DefaultMultipartHttpServletRequest(request) {
         @Override
         protected void initializeMultipart() {
            MultipartParsingResult parsingResult = parseRequest(request); //解析
            //从解析结果中获取 结构,注入到new的request中
            setMultipartFiles(parsingResult.getMultipartFiles());  
            setMultipartParameters(parsingResult.getMultipartParameters());
            setMultipartParameterContentTypes(parsingResult.getMultipartParameterContentTypes());
         }
      };
   }
   else { //与方面功能相同
      MultipartParsingResult parsingResult = parseRequest(request);
      return new DefaultMultipartHttpServletRequest(request, parsingResult.getMultipartFiles(),
            parsingResult.getMultipartParameters(), parsingResult.getMultipartParameterContentTypes());
   }
}

2.getHandler(processedRequest)

    获取当前请求对应的处理类,返回的是请求处理链

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   if (this.handlerMappings != null) {
      for (HandlerMapping hm : this.handlerMappings) { //找到了就退出
         HandlerExecutionChain handler = hm.getHandler(request);//【入】
         if (handler != null) {
            return handler;
         }
      }
   }
   return null;
}

紧接着,跟入getHandler()方法,位于handlerMapping的父类AbstractHandlerMapping中:

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   //子类实现,一个是AbstractHandlerMethodMapping一个是 method换成url
   Object handler = getHandlerInternal(request); //【★】
   if (handler == null) {//为找到,使用默认的处理类
      handler = getDefaultHandler();
   }
   if (handler == null) {
      return null;
   }
   // Bean name or resolved handler?
   if (handler instanceof String) {
      String handlerName = (String) handler;
      handler = obtainApplicationContext().getBean(handlerName);
   }
   //包装为 执行器链
   HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
   if (CorsUtils.isCorsRequest(request)) { //是不是core请求,core是跨域请求
      CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
      CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
      CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
      executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
   }
   return executionChain;
}

    具体的getHandler()稍显复杂,这里我们先不叙述,另开一节,在这个时候拿到了Handler,就调用getHandlerExecutionChain()方法,将Handler包装成执行器链

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
   //强制转换 or 封装
   HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
         (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

   String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
   for (HandlerInterceptor interceptor : this.adaptedInterceptors) {  //遍历
      if (interceptor instanceof MappedInterceptor) {
         MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
         if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
            chain.addInterceptor(mappedInterceptor.getInterceptor());  //添加到执行链中
         }
      }
      else {
         chain.addInterceptor(interceptor); //直接添加
      }
   }
   return chain;
}

回到doDispatch()方法

3.getHandlerAdapter()

    获取适配器,直接遍历,匹配成功直接返回

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   if (this.handlerAdapters != null) {
      for (HandlerAdapter ha : this.handlerAdapters) {
         if (ha.supports(handler)) {
            return ha;
         }
      }
   }
}

4.appliyPreHandler()

    执行器链的拦截方法调用,位于HandlerExecutionChain类中

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
   HandlerInterceptor[] interceptors = getInterceptors();
   if (!ObjectUtils.isEmpty(interceptors)) {
      for (int i = 0; i < interceptors.length; i++) {
         HandlerInterceptor interceptor = interceptors[i];
         if (!interceptor.preHandle(request, response, this.handler)) {
            triggerAfterCompletion(request, response, null);
            return false;
         }
         this.interceptorIndex = i;
      }
   }
   return true;
}

5.ha.handle()

ha是handlerAdapter类, 实际请求处理,返回视图结果,它的实现类很多,走AbstractHandlerMethodAdapter类,最后来到RequestMappingHandlerAdapter类的handleInternal()方法:

protected ModelAndView handleInternal(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

   ModelAndView mav;
   checkRequest(request);

   // Execute invokeHandlerMethod in synchronized block if required.
   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 {
      // No synchronization on session demanded at all...
      mav = invokeHandlerMethod(request, response, handlerMethod);
   }

   if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
      if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
         applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
      }
      else {
         prepareResponse(response);
      }
   }

   return mav;
}

此方法,深入内容很多,这里先暂停

6.processDispatchResult()

    处理最后结果

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
      @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
      @Nullable Exception exception) throws Exception {

   boolean errorView = false;
   //存在异常,返回异常界面
   if (exception != null) {
      if (exception instanceof ModelAndViewDefiningException) {
         mv = ((ModelAndViewDefiningException) exception).getModelAndView();
      }
      else {
         Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
         mv = processHandlerException(request, response, handler, exception);
         errorView = (mv != null);
      }
   }
   // Did the handler return a view to render?
   if (mv != null && !mv.wasCleared()) {
      render(mv, request, response); //解析页面
      if (errorView) {
         WebUtils.clearErrorRequestAttributes(request);
      }
   }
   //调用拦截器的afterCompletion方法
   if (mappedHandler != null) {
      mappedHandler.triggerAfterCompletion(request, response, null);
   }
}

    到这里,整个处理流程介绍完毕,还有许多细节的地方需要补充,比如请求的url如何和我们书写的controller类的method进行对应等等。

参考:https://blog.csdn.net/zknxx/article/details/76599356

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值