• 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     }

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

     
  • 相关阅读:
    手机APP远程空气质量监测应用
    SPI
    2017-10-14
    常量声明
    ios- nil NULL 和 NSNull
    Xcode搭建真机调试环境 图文实例
    ios notification
    集合对象总结
    集合对象(NSSet,NSMutableSet,NSIndexSet)
    词典对象(NSDictionary和NSMutableDictionary)
  • 原文地址:https://www.cnblogs.com/haoerlv/p/8670275.html
Copyright © 2020-2023  润新知