/** * 路径和处理器的映射 * * KEY:路径 {@link #lookupHandler(String, HttpServletRequest)} */ private final Map<String, Object> handlerMap = new LinkedHashMap<>();
registerHandler
注册多个 URL 的处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/** * 注册指定 URL 数组的处理器 * * Register the specified handler for the given URL paths. * @param urlPaths the URLs that the bean should be mapped to * @param beanName the name of the handler bean * @throws BeansException if the handler couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered */ protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException { Assert.notNull(urlPaths, "URL path array must not be null"); // 遍历 urlPath 数组 for (String urlPath : urlPaths) { // 注册处理器 registerHandler(urlPath, beanName); } }
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { Assert.notNull(urlPath, "URL path must not be null"); Assert.notNull(handler, "Handler object must not be null"); Object resolvedHandler = handler;
// Pattern match? // <2.1> 情况二,Pattern 匹配合适的,并添加到 matchingPatterns 中 List<String> matchingPatterns = new ArrayList<>(); for (String registeredPattern : this.handlerMap.keySet()) { if (getPathMatcher().match(registeredPattern, urlPath)) { matchingPatterns.add(registeredPattern); } else if (useTrailingSlashMatch()) { if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) { matchingPatterns.add(registeredPattern +"/"); } } }
// <2.2> 获得首个匹配的结果 String bestMatch = null; Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath); if (!matchingPatterns.isEmpty()) { matchingPatterns.sort(patternComparator); // 排序 if (logger.isTraceEnabled() && matchingPatterns.size() > 1) { logger.trace("Matching patterns " + matchingPatterns); } bestMatch = matchingPatterns.get(0); } if (bestMatch != null) { // <2.3> 获得 bestMatch 对应的处理器 handler = this.handlerMap.get(bestMatch); if (handler == null) { if (bestMatch.endsWith("/")) { handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1)); } if (handler == null) { // 如果获得不到,抛出 IllegalStateException 异常 throw new IllegalStateException( "Could not find handler for best pattern match [" + bestMatch + "]"); } } // Bean name or resolved handler? // <2.4> 如果找到的处理器是 String 类型,则从容器中找到 String 对应的 Bean 类型作为处理器。 if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // <2.5> 空方法,校验处理器。目前暂无子类实现该方法 validateHandler(handler, request); // <2.6> 获得匹配的路径 String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
// There might be multiple 'best patterns', let's make sure we have the correct URI template variables // for all of them // <2.7> 获得路径参数集合 Map<String, String> uriTemplateVariables = new LinkedHashMap<>(); for (String matchingPattern : matchingPatterns) { if (patternComparator.compare(bestMatch, matchingPattern) == 0) { Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars); uriTemplateVariables.putAll(decodedVars); } } if (logger.isTraceEnabled() && uriTemplateVariables.size() > 0) { logger.trace("URI variables " + uriTemplateVariables); } // <2.8> 创建处理器 return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables); }
/** * Expose the path within the current mapping as request attribute. * @param pathWithinMapping the path within the current mapping * @param request the request to expose the path to * @see #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE */ protected void exposePathWithinMapping(String bestMatchingPattern, String pathWithinMapping, HttpServletRequest request) { request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatchingPattern); request.setAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping); }
/** * Expose the URI templates variables as request attribute. * @param uriTemplateVariables the URI template variables * @param request the request to expose the path to * @see #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE */ protected void exposeUriTemplateVariables(Map<String, String> uriTemplateVariables, HttpServletRequest request) { request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); }
match
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
@Override @Nullable public RequestMatchResult match(HttpServletRequest request, String pattern) { // 获得请求路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // 模式匹配,若匹配,则返回 RequestMatchResult 对象 if (getPathMatcher().match(pattern, lookupPath)) { return new RequestMatchResult(pattern, lookupPath, getPathMatcher()); } else if (useTrailingSlashMatch()) { if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) { return new RequestMatchResult(pattern + "/", lookupPath, getPathMatcher()); } } // 不匹配,则返回 null return null; }