自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringMVC核心組件HandlerMapping,你清楚了嗎?

開發(fā) 前端
當(dāng)一個請求過來后Spring是如何進(jìn)行處理的?下面簡單的羅列下請個的過程中核心組件,希望能夠幫助到你。

[[437989]]

概述

當(dāng)一個請求過來后Spring是如何進(jìn)行處理的?下面簡單的羅列下請個的過程中核心組件

SpringMVC處理的流程:

  1. DispatcherServlet 所有請求的入口
  2. HandlerMapping 將請求地址與處理程序關(guān)聯(lián)
  3. HandlerAdapter 真正的處理程序,如執(zhí)行上一步中對應(yīng)的處理程序
  4. HandlerMethodArgumentResolver 對參數(shù)進(jìn)行解析,這里面還涉及到很多其它東西
  5. HanlderMethodReturnValueHandler 對返回值進(jìn)行輸出處理
  6. ViewResolver 當(dāng)上一步返回結(jié)果為ModelAndView時會應(yīng)用視圖解析器

一個請求的處理過程

獲取HandlerMapping

該步從容器中獲取所有的HandlerMapping對象。

  1. public class DispatcherServlet extends FrameworkServlet { 
  2.   private List<HandlerMapping> handlerMappings; 
  3.   private void initHandlerMappings(ApplicationContext context) { 
  4.     // 在ApplicationContext中查找所有HandlerMappings,包括祖先上下文。 
  5.     Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, truefalse); 
  6.     if (!matchingBeans.isEmpty()) { 
  7.       this.handlerMappings = new ArrayList<>(matchingBeans.values()); 
  8.       AnnotationAwareOrderComparator.sort(this.handlerMappings); 
  9.     } 
  10.   } 

查找HandlerMapping

該步從獲取的HandlerMapping中查找適合當(dāng)前請求的HandlerMapping。

  1. public class DispatcherServlet extends FrameworkServlet { 
  2.   private List<HandlerMapping> handlerMappings; 
  3.   protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 
  4.     HandlerExecutionChain mappedHandler = null
  5.     // 查找能夠處理當(dāng)前請求HandlerMapping對象,主要就是根據(jù)請求的URI 
  6.     mappedHandler = getHandler(processedRequest); 
  7.   } 
  8.   protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 
  9.     if (this.handlerMappings != null) { 
  10.       // HandlerMapping 實現(xiàn)了Ordered接口,是由順序的,那在這里,誰先匹配誰就處理 
  11.       for (HandlerMapping mapping : this.handlerMappings) { 
  12.        // 在這個過程中會通過查找到的HandlerMapping對象,然后獲取合適的處理程序(可能是個Bean對象或是HandlerMethod對象等) 
  13.         HandlerExecutionChain handler = mapping.getHandler(request); 
  14.         if (handler != null) { 
  15.           return handler; 
  16.         } 
  17.       } 
  18.     } 
  19.     return null
  20.   } 

系統(tǒng)默認(rèn)有如下5個HandlerMapping

  1. RequestMappingHandlerMapping
  2. BeanNameUrlHandlerMapping
  3. RouterFunctionMapping
  4. SimpleUrlHandlerMapping
  5. WelcomePageHandlerMapping

一般默認(rèn)都是RequestMappingHandlerMapping匹配

接下來看看是如何進(jìn)行匹配的

調(diào)用父類AbstractHandlerMapping#getHandler方法,父類中的這個方法中定義了特定的邏輯,而針對每種不同的HandlerMapping實現(xiàn)是需要具體的子類來實現(xiàn)AbstractHandlerMapping#getHandlerInternal方法

  1. public abstract class AbstractHandlerMapping { 
  2.   public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 
  3.     Object handler = getHandlerInternal(request); 
  4.     // ... 
  5.     HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); 
  6.     // ... 
  7.     return executionChain; 
  8.     } 
  9.    
  10. public abstract class AbstractHandlerMethodMapping { 
  11.   protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { 
  12.     // 獲取請求地址 
  13.     String lookupPath = initLookupPath(request); 
  14.     try { 
  15.       // 根據(jù)請求地址查詢對應(yīng)的HandlerMethod 
  16.       HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); 
  17.       return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); 
  18.     } 
  19.     // ... 
  20.   } 
  21.   protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { 
  22.     List<Match> matches = new ArrayList<>(); 
  23.     // 在已注冊的Mapping中根據(jù)請求的url進(jìn)行查找 
  24.     // 這樣查找的this.pathLookup.get(urlPath); 
  25.     List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath); 
  26.     if (!matches.isEmpty()) { 
  27.       Match bestMatch = matches.get(0); 
  28.       // ... 
  29.       handleMatch(bestMatch.mapping, lookupPath, request); 
  30.       return bestMatch.getHandlerMethod(); 
  31.     } 
  32.     // ... 
  33.   } 

 到這里就是查找處理請求的HandlerMethod對象。接下來看看系統(tǒng)是如何進(jìn)行初始化所有的HandlerMethod

初始化HandlerMethod

  1. public class RequestMappingHandlerMapping { 
  2.   public void afterPropertiesSet() { 
  3.     // ... 
  4.     super.afterPropertiesSet(); 
  5.   } 
  6. public abstract class AbstractHandlerMethodMapping { 
  7.   public void afterPropertiesSet() { 
  8.     initHandlerMethods(); 
  9.   } 
  10.   protected void initHandlerMethods() { 
  11.     // getCandidateBeanNames獲取容器中的所有Bean 
  12.         for (String beanName : getCandidateBeanNames()) { 
  13.       if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { 
  14.         processCandidateBean(beanName); 
  15.       } 
  16.     } 
  17.     handlerMethodsInitialized(getHandlerMethods()); 
  18.   } 
  19.   protected void processCandidateBean(String beanName) { 
  20.     Class<?> beanType = null
  21.     try { 
  22.       // 根據(jù)BeanName獲取對應(yīng)的Class 
  23.       beanType = obtainApplicationContext().getType(beanName); 
  24.     } 
  25.     // ... 
  26.     // isHandler方法判斷當(dāng)前的類是否符合條件,該方法在RequestMappingHandlerMapping中實現(xiàn) 
  27.     // isHandler方法用處就是判斷當(dāng)前的Class@Controller或者@RequestMapping注解 
  28.     // 這樣就將所有的@Controller與RequestMappingHandlerMapping關(guān)聯(lián)一起了。 
  29.     if (beanType != null && isHandler(beanType)) { 
  30.       // 查找所有的HandlerMethod 
  31.       detectHandlerMethods(beanName); 
  32.     } 
  33.   } 
  34.   protected void detectHandlerMethods(Object handler) { 
  35.     Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); 
  36.     if (handlerType != null) { 
  37.       Class<?> userType = ClassUtils.getUserClass(handlerType); 
  38.       // 查找Class中的所有方法 
  39.       Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { 
  40.         try { 
  41.           // 將每一個符合條件的方法(方法上有@RequestMapping注解的) 
  42.           // 封裝到RequestMappingInfo對象中 
  43.           return getMappingForMethod(method, userType); 
  44.         } 
  45.         // ... 
  46.       }); 
  47.       methods.forEach((method, mapping) -> { 
  48.         Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); 
  49.         // 將找到的所有Method進(jìn)行注冊添加到Map中 
  50.         registerHandlerMethod(handler, invocableMethod, mapping); 
  51.       }); 
  52.     } 
  53.   } 
  54.   protected void registerHandlerMethod(Object handler, Method method, T mapping) { 
  55.     this.mappingRegistry.register(mapping, handler, method); 
  56.   } 
  57.   class MappingRegistry { 
  58.     // T  : RequestMappingInfo, handler: 字符串(usersController)Bean名稱,method:請求方法對象 
  59.     public void register(T mapping, Object handler, Method method) { 
  60.       // 創(chuàng)建HandlerMethod對象 
  61.       HandlerMethod handlerMethod = createHandlerMethod(handler, method); 
  62.       // ... 
  63.       for (String path : directPaths) { 
  64.         // 緩存上,在請求到來的時候 會從這個pathLookup集合中查找 
  65.         this.pathLookup.add(path, mapping); 
  66.       } 
  67.     } 
  68.   } 

 

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2021-03-26 11:00:50

SpringMVC組件接口

2024-12-04 09:41:06

2022-12-07 08:56:27

SpringMVC核心組件

2024-03-27 13:33:00

MySQLInnoDB事務(wù)

2022-07-11 08:48:52

業(yè)務(wù)轉(zhuǎn)型CIO

2024-04-01 08:29:09

Git核心實例

2024-09-09 12:00:34

2022-10-24 00:33:59

MySQL全局鎖行級鎖

2023-06-07 14:07:00

架構(gòu)

2018-10-25 09:26:07

VLANVXLAN網(wǎng)絡(luò)

2022-01-05 07:07:37

Go核心設(shè)計

2012-01-13 13:05:41

Scale Out網(wǎng)絡(luò)

2021-10-12 10:50:31

鴻蒙HarmonyOS應(yīng)用

2023-11-10 10:51:15

Python

2010-09-01 09:48:32

DHCP報文格式

2012-03-12 13:47:05

移動廣告

2013-07-15 16:55:45

2012-08-29 09:44:20

免費增值

2009-06-22 14:36:09

ITIL運維管理摩卡軟件

2010-08-04 15:01:00

點贊
收藏

51CTO技術(shù)棧公眾號