最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談SpringMVC請(qǐng)求映射handler源碼解讀

 更新時(shí)間:2021年03月18日 09:18:23   作者:是馮吉榮呀  
這篇文章主要介紹了淺談SpringMVC請(qǐng)求映射handler源碼解讀,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

請(qǐng)求映射源碼

首先看一張請(qǐng)求完整流轉(zhuǎn)圖(這里感謝博客園上這位大神的圖,博客地址我忘記了):

前臺(tái)發(fā)送給后臺(tái)的訪問請(qǐng)求是如何找到對(duì)應(yīng)的控制器映射并執(zhí)行后續(xù)的后臺(tái)操作呢,其核心為DispatcherServlet.java與HandlerMapper。在spring boot初始化的時(shí)候,將會(huì)加載所有的請(qǐng)求與對(duì)應(yīng)的處理器映射為HandlerMapper組件。我們可以在springMVC的自動(dòng)配置類中找到對(duì)應(yīng)的Bean。

@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping(
  @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
  @Qualifier("mvcConversionService") FormattingConversionService conversionService,
  @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
  // Must be @Primary for MvcUriComponentsBuilder to work
  return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,
                       resourceUrlProvider);
}

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
                              FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
  WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
    new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
    this.mvcProperties.getStaticPathPattern());
  welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
  welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
  return welcomePageHandlerMapping;
}

請(qǐng)求將首先執(zhí)行FrameworkServlet下的service方法根據(jù)request請(qǐng)求的method找到對(duì)應(yīng)的do**方法。

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

  HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
  if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
    processRequest(request, response);
  }
  else {
    //父類根據(jù)method參數(shù)執(zhí)行doGet,doPost,doDelete等
    super.service(request, response);
  }
}

而這些do**其都會(huì)進(jìn)入核心方法,以doGet為例。

@Overrideprotected 
final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  //核心方法
  processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  try {
  //進(jìn)入此核心方法
  doService(request, response);
}
catch (ServletException | IOException ex) {
  failureCause = ex;
  throw ex;
}
catch (Throwable ex) {
  failureCause = ex;
  throw new NestedServletException("Request processing failed", ex);
}

finally {
  resetContextHolders(request, previousLocaleContext, previousAttributes);
  if (requestAttributes != null) {
    requestAttributes.requestCompleted();
  }
  logResult(request, response, failureCause, asyncManager);
  publishRequestHandledEvent(request, response, startTime, failureCause);
}

processRequest()方法中重點(diǎn)在doService(request, response);,而其核心處理邏輯位于DispatchServletl類重寫的方法,如下。

@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
 ····

   try {
     //這里為實(shí)際分發(fā)控制器的邏輯,其內(nèi)部是找到對(duì)應(yīng)的handlerMapper
     doDispatch(request, response);
   }
    finally {
      if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        // Restore the original attribute snapshot, in case of an include.
        if (attributesSnapshot != null) {
          restoreAttributesAfterInclude(request, attributesSnapshot);
        }
      }
      if (requestPath != null) {
        ServletRequestPathUtils.clearParsedRequestPath(request);
      }
    }
}

接下來看分發(fā)處理邏輯方法,其中重要的方法都使用了原生的注釋。接下來分別分析核心源碼。

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 {
      processedRequest = checkMultipart(request);
      multipartRequestParsed = (processedRequest != request);

      // Determine handler for the current request.
      mappedHandler = getHandler(processedRequest);
      if (mappedHandler == null) {
        noHandlerFound(processedRequest, response);
        return;
      }

      // Determine handler adapter for the current request.
      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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
          return;
        }
      }

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

      // Actually invoke the handler.
      mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

      if (asyncManager.isConcurrentHandlingStarted()) {
        return;
      }

      applyDefaultViewName(processedRequest, mv);
      mappedHandler.applyPostHandle(processedRequest, response, mv);
    }
    catch (Exception ex) {
      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.
      dispatchException = new NestedServletException("Handler dispatch failed", err);
    }
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  }
  catch (Exception ex) {
    triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
  }
  catch (Throwable err) {
    triggerAfterCompletion(processedRequest, response, mappedHandler,
                new NestedServletException("Handler processing failed", err));
  }
  finally {
    if (asyncManager.isConcurrentHandlingStarted()) {
      // Instead of postHandle and afterCompletion
      if (mappedHandler != null) {
        mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
      }
    }
    else {
      // Clean up any resources used by a multipart request.
      if (multipartRequestParsed) {
        cleanupMultipart(processedRequest);
      }
    }
  }
}

首先是分析getHandler(),找到對(duì)應(yīng)的處理器映射邏輯。

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  if (this.handlerMappings != null) {
    for (HandlerMapping mapping : this.handlerMappings) {
      HandlerExecutionChain handler = mapping.getHandler(request);
      if (handler != null) {
        return handler;
      }
    }
  }
  return null;
}

我們將斷點(diǎn)標(biāo)記在getHandler方法上時(shí),可以清除看到handlerMappings,如圖。

這里,用戶請(qǐng)求與處理器的映射關(guān)系都在RequestMapperHandlerMapping中,而歡迎頁處理請(qǐng)求則在WelcomePageHanderMapping中進(jìn)行映射。

以下為RequestMapperHandlerMapping中映射部分截圖,可以看到用戶的所有請(qǐng)求映射這里面都有:

getHandler()后的方法是通過比較request請(qǐng)求中method與HandlerMapper中相同url下的method,再進(jìn)行唯一性校驗(yàn),不通過異常,通過找到唯一的handler。

后續(xù),通過handler找到處理的設(shè)配器,通過適配器得到一個(gè)ModelAndView對(duì)象,這個(gè)對(duì)象就是最后返回給前端頁面的對(duì)象。

至此,一個(gè)請(qǐng)求完整映射到返回前端結(jié)束。

說明:這是實(shí)現(xiàn)了FramworkServlet的doService方法,F(xiàn)ramworkServlet繼承自HttpServlet,并且重寫了父類中的doGet(),doPost(),doPut(),doDelete 等方法,在這些重寫的方法里都調(diào)用了 processRquest() 方法做請(qǐng)求處理,進(jìn)入processRquest()可以看到里面調(diào)用了FramworkServlet中定義的doService() 方法。

到此這篇關(guān)于淺談SpringMVC請(qǐng)求映射handler源碼解讀的文章就介紹到這了,更多相關(guān)SpringMVC請(qǐng)求映射handler 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解RestTemplate?用法

    詳解RestTemplate?用法

    RestTemplate?是從?Spring3.0?開始支持的一個(gè)?HTTP?請(qǐng)求工具,也有的稱之為網(wǎng)絡(luò)框架,說白了就是Java版本的一個(gè)postman,這篇文章主要介紹了詳解RestTemplate?用法,需要的朋友可以參考下
    2022-07-07
  • 詳解Spring注解@Autowired的實(shí)現(xiàn)原理和使用方法

    詳解Spring注解@Autowired的實(shí)現(xiàn)原理和使用方法

    在使用Spring開發(fā)的時(shí)候,配置的方式主要有兩種,一種是xml的方式,另外一種是 java config的方式,在使用的過程中,我們使用最多的注解應(yīng)該就是@Autowired注解了,所以本文就給大家講講@Autowired注解是如何使用和實(shí)現(xiàn)的,需要的朋友可以參考下
    2023-07-07
  • Spring5新功能@Nullable注解及函數(shù)式注冊(cè)對(duì)象

    Spring5新功能@Nullable注解及函數(shù)式注冊(cè)對(duì)象

    這篇文章主要為大家介紹了Spring5新功能詳解@Nullable注解及函數(shù)式注冊(cè)對(duì)象,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • MyBatis根據(jù)條件批量修改字段的方式

    MyBatis根據(jù)條件批量修改字段的方式

    這篇文章主要介紹了MyBatis根據(jù)條件批量修改字段的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Idea打不了斷點(diǎn)如何解決

    Idea打不了斷點(diǎn)如何解決

    這篇文章主要介紹了Idea打不了斷點(diǎn)如何解決的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • mybatis?plus自動(dòng)生成代碼的示例代碼

    mybatis?plus自動(dòng)生成代碼的示例代碼

    本文主要介紹了mybatis?plus自動(dòng)生成代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 基于String變量的兩種創(chuàng)建方式(詳解)

    基于String變量的兩種創(chuàng)建方式(詳解)

    下面小編就為大家?guī)硪黄赟tring變量的兩種創(chuàng)建方式(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Windows安裝Maven并配置環(huán)境的詳細(xì)步驟

    Windows安裝Maven并配置環(huán)境的詳細(xì)步驟

    Maven是一個(gè)非常流行的構(gòu)建和項(xiàng)目管理工具,用于Java開發(fā),它提供了一個(gè)強(qiáng)大的依賴管理系統(tǒng)和一系列標(biāo)準(zhǔn)化的構(gòu)建生命周期,本文將指導(dǎo)您如何在Windows操作系統(tǒng)上安裝和配置Maven,需要的朋友可以參考下
    2023-05-05
  • springboot vue組件開發(fā)實(shí)現(xiàn)接口斷言功能

    springboot vue組件開發(fā)實(shí)現(xiàn)接口斷言功能

    這篇文章主要為大家介紹了springboot+vue組件開發(fā)實(shí)現(xiàn)接口斷言功能,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • java線程池使用及原理面試題

    java線程池使用及原理面試題

    很多面試官喜歡把線程池作為問題的起點(diǎn),然后延伸到其它內(nèi)容,由于我們專欄已經(jīng)說過隊(duì)列、線程、鎖面試題了,所以本章面試題還是以線程池為主
    2022-03-03

最新評(píng)論

岫岩| 钟山县| 韶山市| 新巴尔虎左旗| 余庆县| 比如县| 六枝特区| 嵊州市| 攀枝花市| 通辽市| 新干县| 桐乡市| 水城县| 通渭县| 和林格尔县| 广汉市| 枣强县| 宁远县| 成安县| 东乡| 万宁市| 连城县| 故城县| 习水县| 徐汇区| 奇台县| 峨边| 噶尔县| 齐河县| 曲周县| 房山区| 凤翔县| 新源县| 方山县| 清苑县| 通山县| 宝鸡市| 萨嘎县| 蒙城县| 元氏县| 贡觉县|