这个思路同样是通过在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 }
实际上这一步是又匹配了一遍,没有在返回空, 有的话 就报异常