Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)

这个思路同样是通过在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     }

实际上这一步是又匹配了一遍,没有在返回空, 有的话 就报异常

 
原文地址:https://www.cnblogs.com/haoerlv/p/8670275.html