這個思路同樣是通過在AbstractHandlerMethodMapping里面來實現getHandlerInternal()實現自己的方法來處理尋找正確的處理器,不懂得請看上一篇。
1 protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { 2 String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); //同樣從請求中獲取url 3 if (this.logger.isDebugEnabled()) { 4 this.logger.debug("Looking up handler method for path " + lookupPath); 5 } 6 7 HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);//查找handler 8 if (this.logger.isDebugEnabled()) { 9 if (handlerMethod != null) { 10 this.logger.debug("Returning handler method [" + handlerMethod + "]"); 11 } else { 12 this.logger.debug("Did not find handler method for [" + lookupPath + "]"); 13 } 14 } 15 16 return handlerMethod != null ? handlerMethod.createWithResolvedBean() : null; //這塊應該是為handler添加一些東西,參數等, 17 }
1 protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { 2 List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList(); 3 List<T> directPathMatches = (List)this.urlMap.get(lookupPath); //找到匹配url的匹配條件List 4 if (directPathMatches != null) { 5 this.addMatchingMappings(directPathMatches, matches, request); //添加匹配對象 Match實際上是匹配條件,和處理器的封裝對象 6 } 7 8 if (matches.isEmpty()) { 9 this.addMatchingMappings(this.handlerMethods.keySet(), matches, request); 10 } 11 12 if (!matches.isEmpty()) { 13 Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request)); 14 Collections.sort(matches, comparator); 15 if (this.logger.isTraceEnabled()) { 16 this.logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches); 17 } 18 //如果多個匹配條件,進行排序,子類自己實現比較方法,然后取第一個 19 AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0); 20 if (matches.size() > 1) { //如果存在兩個復核條件的一樣的處理器,則報錯 21 AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1); 22 if (comparator.compare(bestMatch, secondBestMatch) == 0) { 23 Method m1 = bestMatch.handlerMethod.getMethod(); 24 Method m2 = secondBestMatch.handlerMethod.getMethod(); 25 throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}"); 26 } 27 } 28 29 this.handleMatch(bestMatch.mapping, lookupPath, request); //實際上緩存到request域中 //這塊子類也復寫了,應該是多緩存了些東西 30 return bestMatch.handlerMethod; 31 } else { 32 return this.handleNoMatch(this.handlerMethods.keySet(), lookupPath, request); //沒找到子類已進行了復寫 33 } 34 }
RequestMappingInfoHandlerMapping 中 handleNoMatch 的實現
1 protected HandlerMethod handleNoMatch(Set<RequestMappingInfo> requestMappingInfos, String lookupPath, HttpServletRequest request) throws ServletException { 2 Set<String> allowedMethods = new HashSet(6); 3 Set<RequestMappingInfo> patternMatches = new HashSet(); 4 Set<RequestMappingInfo> patternAndMethodMatches = new HashSet(); 5 Iterator i$ = requestMappingInfos.iterator(); 6 7 while(true) { 8 while(true) { 9 RequestMappingInfo info; 10 do { 11 if (!i$.hasNext()) { 12 if (patternMatches.isEmpty()) { 13 return null; 14 } 15 16 if (patternAndMethodMatches.isEmpty() && !allowedMethods.isEmpty()) { 17 throw new HttpRequestMethodNotSupportedException(request.getMethod(), allowedMethods); 18 } 19 20 Set consumableMediaTypes; 21 Set producibleMediaTypes; 22 if (patternAndMethodMatches.isEmpty()) { 23 consumableMediaTypes = this.getConsumableMediaTypes(request, patternMatches); 24 producibleMediaTypes = this.getProdicubleMediaTypes(request, patternMatches); 25 } else { 26 consumableMediaTypes = this.getConsumableMediaTypes(request, patternAndMethodMatches); 27 producibleMediaTypes = this.getProdicubleMediaTypes(request, patternAndMethodMatches); 28 } 29 30 if (!consumableMediaTypes.isEmpty()) { 31 MediaType contentType = null; 32 if (StringUtils.hasLength(request.getContentType())) { 33 contentType = MediaType.parseMediaType(request.getContentType()); 34 } 35 36 throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList(consumableMediaTypes)); 37 } 38 39 if (!producibleMediaTypes.isEmpty()) { 40 throw new HttpMediaTypeNotAcceptableException(new ArrayList(producibleMediaTypes)); 41 } 42 43 return null; 44 } 45 46 info = (RequestMappingInfo)i$.next(); 47 } while(info.getPatternsCondition().getMatchingCondition(request) == null); 48 49 patternMatches.add(info); 50 if (info.getMethodsCondition().getMatchingCondition(request) != null) { 51 patternAndMethodMatches.add(info); 52 } else { 53 Iterator i$ = info.getMethodsCondition().getMethods().iterator(); 54 55 while(i$.hasNext()) { 56 RequestMethod method = (RequestMethod)i$.next(); 57 allowedMethods.add(method.name()); 58 } 59 } 60 } 61 } 62 }
實際上這一步是又匹配了一遍,沒有在返回空, 有的話 就報異常