上一節咱們分析了RequestMappingHandlerMapping的初始化過程,即建立並註冊HandlerMehtod,本章咱們分析下RequestMappingHandlerMapping的請求處理過程,即查找HandlerMethod。前端
本系列文章是基於Spring5.0.5RELEASE。segmentfault
因本節重點分析RequestMappingHandlerMapping處理請求方式,因此咱們從請求到達前端控制器(DispatcherServlet)的doDispatch方法開始,以前的請求處理可參考http://www.javashuo.com/article/p-njjdktrq-kw.html跨域
流程描述:數組
處理用戶請求的方法到達doDispatch方法,源碼以下:app
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // ... ... //查找請求的處理器 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { // 未找處處理器時跑異常 noHandlerFound(processedRequest, response); return; } // ... ... } @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { // 迭代Spring支持的HandlerMapping,即咱們配置或默認的HandlerMapping for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } // 查找請求的處理器HandlerExecutionChain,包括請求須要的攔截器 HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } } return null; }
提供查出處理器模板方法,具體實現由子類實現getHandlerInternal方法實現,代碼以下:ide
@Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 子類需實現getHandlerInternal方法,本例中由AbstractHandlerMethodMapping實現 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // 若是handler是bean名字,則根據名字從上下文獲取處處理類 if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // 返回請求處理的HandlerExecutionChain對象 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 對跨域的處理 if (CorsUtils.isCorsRequest(request)) { 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; }
本類主要提供建立並註冊HandlerMethod以及查找HandlerMethod功能,處理用戶請求時,源碼以下:函數
/** * 實現父類(AbstractHandlerMapping)的鉤子函數 */ @Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 使用工具類UrlPathHelper,解析用戶請求url String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); if (logger.isDebugEnabled()) { logger.debug("Looking up handler method for path " + lookupPath); } this.mappingRegistry.acquireReadLock(); try { // 查找HandlerMethod核心方法 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); if (logger.isDebugEnabled()) { if (handlerMethod != null) { logger.debug("Returning handler method [" + handlerMethod + "]"); } else { logger.debug("Did not find handler method for [" + lookupPath + "]"); } } return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } } /** * 查找當前請求的處理器方法 */ @Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { // 定義匹配到的matches集合,其內存放匹配到的Match對象 List<Match> matches = new ArrayList<>(); // 根據請求url查找出RequestMappingInfo對象 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { // 將查找到的RequestMappingInfo和處理器方法封裝成Match對象存入到matches數組 addMatchingMappings(directPathMatches, matches, request); } // 爲查詢到RequestMappingInfo時 if (matches.isEmpty()) { // this.mappingRegistry.getMappings().keySet()--返回已註冊全部的RequestMappingInfo // 查找到將RequestMappingInfo和處理器方法封裝後存入matches數組 addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } // 有匹配對象 if (!matches.isEmpty()) { // 排序處理 Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); if (logger.isTraceEnabled()) { logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches); } // 取出Match,其封裝了RequestMappingInfo和處理器方法 Match bestMatch = matches.get(0); if (matches.size() > 1) { if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}"); } } // 主要是往Request的Attribute區放了些東西,具體啥用我也不懂 handleMatch(bestMatch.mapping, lookupPath, request); // 返回處理器方法HandlerMethod return bestMatch.handlerMethod; } else { // 未找處處理 return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
本節對RequestMappingHandlerMapping處理用戶請求時的總體流程及核心源碼進行了分析,若有問題或建議你們可掃描下方二維碼進羣反饋,我會知無不言言無不盡,但願對你們有所幫助。工具
最後建立了qq羣方便你們交流,可掃描加入,同時也可加我qq:276420284,共同窗習、共同進步,謝謝!源碼分析