需求:客户代理的每个http请求都要进行权限验证,如果无权限不能调用服务接口.
实现思路:
由拦截器统一拦截所有请求,在拦截器的preHandle方法中通过传入的request参数获取到将要调用的实际类与方法,用户ticket等信息
每个要进行权限控制的方法都要添加注脚标明其权限码,如:@funcCode("1001")
拦截器获取方法的注脚,与redis中该用户的权限码清单比较.如果有就允许调用,否则拒绝调用.
技术要点:
在拦截器中获取到该请求将要调用的类与方法.调用的类已经由preHandle传入,但是具体调用那个方法确没有提供.
话不多说
由spring mvc架构可知,每个请求都由DispacherServlet的doDispatch分发,进入源码查看,关键在截图的最后一句
ha变量的实现类,在我的的spring配置使用的是AnnotationMethodHandlerAdapter(该类在4.X中已被弃用,使用较新spring版本的请自行换成RequestMappingHandlerAdapter)
如果使用RequestMappingHandlerAdapter已经不需要这么繁琐了.spring已经意识到有人需要得到具体调用的方法,所以拦截器的入参类型已经是HandlerMethod.本文只是针对旧版本的的spring框架适用.
进入查看
ha.handle又调用了invokeHandlerMethod方法
里面有这么一句
ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
Method handlerMethod = methodResolver.resolveHandlerMethod(request);
ServletHandlerMethodInvoker 是一个内部类resolveHandlerMethod方法正是我们要的.
然后就是搬代码,把获取spring里获取方法有关的代码都搬出去,

1 private UrlPathHelper urlPathHelper = new UrlPathHelper(); 2 3 private PathMatcher pathMatcher = new AntPathMatcher(); 4 5 private org.springframework.web.servlet.mvc.multiaction.MethodNameResolver methodNameResolver = new org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver(); 6 7 private final Map<Class<?>, ServletHandlerMethodResolver> methodResolverCache = new ConcurrentHashMap<Class<?>, ServletHandlerMethodResolver>( 8 64); 9 10 static class ServletAnnotationMappingUtils { 11 12 /** 13 * Check whether the given request matches the specified request 14 * methods. 15 * 16 * @param methods 17 * the HTTP request methods to check against 18 * @param request 19 * the current HTTP request to check 20 */ 21 public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) { 22 String inputMethod = request.getMethod(); 23 if (ObjectUtils.isEmpty(methods) && !RequestMethod.OPTIONS.name().equals(inputMethod)) { 24 return true; 25 } 26 for (RequestMethod method : methods) { 27 if (method.name().equals(inputMethod)) { 28 return true; 29 } 30 } 31 return false; 32 } 33 34 /** 35 * Check whether the given request matches the specified parameter 36 * conditions. 37 * 38 * @param params 39 * the parameter conditions, following 40 * {@link org.springframework.web.bind.annotation.RequestMapping#params() 41 * RequestMapping.#params()} 42 * @param request 43 * the current HTTP request to check 44 */ 45 public static boolean checkParameters(String[] params, HttpServletRequest request) { 46 if (!ObjectUtils.isEmpty(params)) { 47 for (String param : params) { 48 int separator = param.indexOf('='); 49 if (separator == -1) { 50 if (param.startsWith("!")) { 51 if (WebUtils.hasSubmitParameter(request, param.substring(1))) { 52 return false; 53 } 54 } else if (!WebUtils.hasSubmitParameter(request, param)) { 55 return false; 56 } 57 } else { 58 boolean negated = separator > 0 && param.charAt(separator - 1) == '!'; 59 String key = !negated ? param.substring(0, separator) : param.substring(0, separator - 1); 60 String value = param.substring(separator + 1); 61 boolean match = value.equals(request.getParameter(key)); 62 if (negated) { 63 match = !match; 64 } 65 if (!match) { 66 return false; 67 } 68 } 69 } 70 } 71 return true; 72 } 73 74 /** 75 * Check whether the given request matches the specified header 76 * conditions. 77 * 78 * @param headers 79 * the header conditions, following 80 * {@link org.springframework.web.bind.annotation.RequestMapping#headers() 81 * RequestMapping.headers()} 82 * @param request 83 * the current HTTP request to check 84 */ 85 public static boolean checkHeaders(String[] headers, HttpServletRequest request) { 86 if (!ObjectUtils.isEmpty(headers)) { 87 for (String header : headers) { 88 int separator = header.indexOf('='); 89 if (separator == -1) { 90 if (header.startsWith("!")) { 91 if (request.getHeader(header.substring(1)) != null) { 92 return false; 93 } 94 } else if (request.getHeader(header) == null) { 95 return false; 96 } 97 } else { 98 boolean negated = (separator > 0 && header.charAt(separator - 1) == '!'); 99 String key = !negated ? header.substring(0, separator) : header.substring(0, separator - 1); 100 String value = header.substring(separator + 1); 101 if (isMediaTypeHeader(key)) { 102 List<MediaType> requestMediaTypes = MediaType.parseMediaTypes(request.getHeader(key)); 103 List<MediaType> valueMediaTypes = MediaType.parseMediaTypes(value); 104 boolean found = false; 105 for (Iterator<MediaType> valIter = valueMediaTypes.iterator(); valIter.hasNext() 106 && !found;) { 107 MediaType valueMediaType = valIter.next(); 108 for (Iterator<MediaType> reqIter = requestMediaTypes.iterator(); reqIter.hasNext() 109 && !found;) { 110 MediaType requestMediaType = reqIter.next(); 111 if (valueMediaType.includes(requestMediaType)) { 112 found = true; 113 } 114 } 115 116 } 117 if (negated) { 118 found = !found; 119 } 120 if (!found) { 121 return false; 122 } 123 } else { 124 boolean match = value.equals(request.getHeader(key)); 125 if (negated) { 126 match = !match; 127 } 128 if (!match) { 129 return false; 130 } 131 } 132 } 133 } 134 } 135 return true; 136 } 137 138 private static boolean isMediaTypeHeader(String headerName) { 139 return ("Accept".equalsIgnoreCase(headerName) || "Content-Type".equalsIgnoreCase(headerName)); 140 } 141 142 } 143 144 /** 145 * Comparator capable of sorting {@link RequestSpecificMappingInfo}s (RHIs) 146 * so that sorting a list with this comparator will result in: 147 * <ul> 148 * <li>RHIs with 149 * {@linkplain AnnotationMethodHandlerAdapter.RequestSpecificMappingInfo#matchedPatterns 150 * better matched paths} take precedence over those with a weaker match (as 151 * expressed by the {@linkplain PathMatcher#getPatternComparator(String) 152 * path pattern comparator}.) Typically, this means that patterns without 153 * wild cards and uri templates will be ordered before those without.</li> 154 * <li>RHIs with one single {@linkplain RequestMappingInfo#methods request 155 * method} will be ordered before those without a method, or with more than 156 * one method.</li> 157 * <li>RHIs with more {@linkplain RequestMappingInfo#params request 158 * parameters} will be ordered before those with less parameters</li> 159 * </ol> 160 */ 161 static class RequestSpecificMappingInfoComparator implements Comparator<RequestSpecificMappingInfo> { 162 163 private final Comparator<String> pathComparator; 164 165 private final ServerHttpRequest request; 166 167 RequestSpecificMappingInfoComparator(Comparator<String> pathComparator, HttpServletRequest request) { 168 this.pathComparator = pathComparator; 169 this.request = new ServletServerHttpRequest(request); 170 } 171 172 @Override 173 public int compare(RequestSpecificMappingInfo info1, RequestSpecificMappingInfo info2) { 174 int pathComparison = pathComparator.compare(info1.bestMatchedPattern(), info2.bestMatchedPattern()); 175 if (pathComparison != 0) { 176 return pathComparison; 177 } 178 int info1ParamCount = info1.getParamCount(); 179 int info2ParamCount = info2.getParamCount(); 180 if (info1ParamCount != info2ParamCount) { 181 return info2ParamCount - info1ParamCount; 182 } 183 int info1HeaderCount = info1.getHeaderCount(); 184 int info2HeaderCount = info2.getHeaderCount(); 185 if (info1HeaderCount != info2HeaderCount) { 186 return info2HeaderCount - info1HeaderCount; 187 } 188 int acceptComparison = compareAcceptHeaders(info1, info2); 189 if (acceptComparison != 0) { 190 return acceptComparison; 191 } 192 int info1MethodCount = info1.getMethodCount(); 193 int info2MethodCount = info2.getMethodCount(); 194 if (info1MethodCount == 0 && info2MethodCount > 0) { 195 return 1; 196 } else if (info2MethodCount == 0 && info1MethodCount > 0) { 197 return -1; 198 } else if (info1MethodCount == 1 & info2MethodCount > 1) { 199 return -1; 200 } else if (info2MethodCount == 1 & info1MethodCount > 1) { 201 return 1; 202 } 203 return 0; 204 } 205 206 private int compareAcceptHeaders(RequestMappingInfo info1, RequestMappingInfo info2) { 207 List<MediaType> requestAccepts = request.getHeaders().getAccept(); 208 MediaType.sortByQualityValue(requestAccepts); 209 210 List<MediaType> info1Accepts = getAcceptHeaderValue(info1); 211 List<MediaType> info2Accepts = getAcceptHeaderValue(info2); 212 213 for (MediaType requestAccept : requestAccepts) { 214 int pos1 = indexOfIncluded(info1Accepts, requestAccept); 215 int pos2 = indexOfIncluded(info2Accepts, requestAccept); 216 if (pos1 != pos2) { 217 return pos2 - pos1; 218 } 219 } 220 return 0; 221 } 222 223 private int indexOfIncluded(List<MediaType> infoAccepts, MediaType requestAccept) { 224 for (int i = 0; i < infoAccepts.size(); i++) { 225 MediaType info1Accept = infoAccepts.get(i); 226 if (requestAccept.includes(info1Accept)) { 227 return i; 228 } 229 } 230 return -1; 231 } 232 233 private List<MediaType> getAcceptHeaderValue(RequestMappingInfo info) { 234 for (String header : info.headers) { 235 int separator = header.indexOf('='); 236 if (separator != -1) { 237 String key = header.substring(0, separator); 238 String value = header.substring(separator + 1); 239 if ("Accept".equalsIgnoreCase(key)) { 240 return MediaType.parseMediaTypes(value); 241 } 242 } 243 } 244 return Collections.emptyList(); 245 } 246 } 247 248 /** 249 * Subclass of {@link RequestMappingInfo} that holds request-specific data. 250 */ 251 static class RequestSpecificMappingInfo extends RequestMappingInfo { 252 253 private final List<String> matchedPatterns = new ArrayList<String>(); 254 255 RequestSpecificMappingInfo(String[] patterns, RequestMethod[] methods, String[] params, String[] headers) { 256 super(patterns, methods, params, headers); 257 } 258 259 RequestSpecificMappingInfo(RequestMappingInfo other) { 260 super(other.patterns, other.methods, other.params, other.headers); 261 } 262 263 public void addMatchedPattern(String matchedPattern) { 264 matchedPatterns.add(matchedPattern); 265 } 266 267 public void sortMatchedPatterns(Comparator<String> pathComparator) { 268 Collections.sort(matchedPatterns, pathComparator); 269 } 270 271 public String bestMatchedPattern() { 272 return (!this.matchedPatterns.isEmpty() ? this.matchedPatterns.get(0) : null); 273 } 274 } 275 276 /** 277 * Holder for request mapping metadata. 278 */ 279 static class RequestMappingInfo { 280 281 private final String[] patterns; 282 283 private final RequestMethod[] methods; 284 285 private final String[] params; 286 287 private final String[] headers; 288 289 RequestMappingInfo(String[] patterns, RequestMethod[] methods, String[] params, String[] headers) { 290 this.patterns = (patterns != null ? patterns : new String[0]); 291 this.methods = (methods != null ? methods : new RequestMethod[0]); 292 this.params = (params != null ? params : new String[0]); 293 this.headers = (headers != null ? headers : new String[0]); 294 } 295 296 public boolean hasPatterns() { 297 return (this.patterns.length > 0); 298 } 299 300 public String[] getPatterns() { 301 return this.patterns; 302 } 303 304 public int getMethodCount() { 305 return this.methods.length; 306 } 307 308 public int getParamCount() { 309 return this.params.length; 310 } 311 312 public int getHeaderCount() { 313 return this.headers.length; 314 } 315 316 public boolean matches(HttpServletRequest request) { 317 return matchesRequestMethod(request) && matchesParameters(request) && matchesHeaders(request); 318 } 319 320 public boolean matchesHeaders(HttpServletRequest request) { 321 322 return ServletAnnotationMappingUtils.checkHeaders(this.headers, request); 323 } 324 325 public boolean matchesParameters(HttpServletRequest request) { 326 return ServletAnnotationMappingUtils.checkParameters(this.params, request); 327 } 328 329 public boolean matchesRequestMethod(HttpServletRequest request) { 330 return ServletAnnotationMappingUtils.checkRequestMethod(this.methods, request); 331 } 332 333 public Set<String> methodNames() { 334 Set<String> methodNames = new LinkedHashSet<String>(this.methods.length); 335 for (RequestMethod method : this.methods) { 336 methodNames.add(method.name()); 337 } 338 return methodNames; 339 } 340 341 @Override 342 public boolean equals(Object obj) { 343 RequestMappingInfo other = (RequestMappingInfo) obj; 344 return (Arrays.equals(this.patterns, other.patterns) && Arrays.equals(this.methods, other.methods) 345 && Arrays.equals(this.params, other.params) && Arrays.equals(this.headers, other.headers)); 346 } 347 348 @Override 349 public int hashCode() { 350 return (Arrays.hashCode(this.patterns) * 23 + Arrays.hashCode(this.methods) * 29 351 + Arrays.hashCode(this.params) * 31 + Arrays.hashCode(this.headers)); 352 } 353 354 @Override 355 public String toString() { 356 StringBuilder builder = new StringBuilder(); 357 builder.append(Arrays.asList(this.patterns)); 358 if (this.methods.length > 0) { 359 builder.append(','); 360 builder.append(Arrays.asList(this.methods)); 361 } 362 if (this.headers.length > 0) { 363 builder.append(','); 364 builder.append(Arrays.asList(this.headers)); 365 } 366 if (this.params.length > 0) { 367 builder.append(','); 368 builder.append(Arrays.asList(this.params)); 369 } 370 return builder.toString(); 371 } 372 } 373 374 /** 375 * Servlet-specific subclass of {@code HandlerMethodResolver}. 376 */ 377 @SuppressWarnings("deprecation") 378 private class ServletHandlerMethodResolver 379 extends org.springframework.web.bind.annotation.support.HandlerMethodResolver { 380 381 private final Map<Method, RequestMappingInfo> mappings = new HashMap<Method, RequestMappingInfo>(); 382 383 private ServletHandlerMethodResolver(Class<?> handlerType) { 384 init(handlerType); 385 } 386 387 @Override 388 protected boolean isHandlerMethod(Method method) { 389 if (this.mappings.containsKey(method)) { 390 return true; 391 } 392 RequestMapping mapping = AnnotationUtils.findAnnotation(method, RequestMapping.class); 393 if (mapping != null) { 394 String[] patterns = mapping.value(); 395 RequestMethod[] methods = new RequestMethod[0]; 396 String[] params = new String[0]; 397 String[] headers = new String[0]; 398 if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) { 399 methods = mapping.method(); 400 } 401 if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) { 402 params = mapping.params(); 403 } 404 if (!hasTypeLevelMapping() || !Arrays.equals(mapping.headers(), getTypeLevelMapping().headers())) { 405 headers = mapping.headers(); 406 } 407 RequestMappingInfo mappingInfo = new RequestMappingInfo(patterns, methods, params, headers); 408 this.mappings.put(method, mappingInfo); 409 return true; 410 } 411 return false; 412 } 413 414 public Method resolveHandlerMethod(HttpServletRequest request) throws ServletException { 415 String lookupPath = urlPathHelper.getLookupPathForRequest(request); 416 Comparator<String> pathComparator = pathMatcher.getPatternComparator(lookupPath); 417 Map<RequestSpecificMappingInfo, Method> targetHandlerMethods = new LinkedHashMap<RequestSpecificMappingInfo, Method>(); 418 Set<String> allowedMethods = new LinkedHashSet<String>(7); 419 String resolvedMethodName = null; 420 for (Method handlerMethod : getHandlerMethods()) { 421 RequestSpecificMappingInfo mappingInfo = new RequestSpecificMappingInfo( 422 this.mappings.get(handlerMethod)); 423 boolean match = false; 424 if (mappingInfo.hasPatterns()) { 425 for (String pattern : mappingInfo.getPatterns()) { 426 if (!hasTypeLevelMapping() && !pattern.startsWith("/")) { 427 pattern = "/" + pattern; 428 } 429 String combinedPattern = getCombinedPattern(pattern, lookupPath, request); 430 if (combinedPattern != null) { 431 if (mappingInfo.matches(request)) { 432 match = true; 433 mappingInfo.addMatchedPattern(combinedPattern); 434 } else { 435 if (!mappingInfo.matchesRequestMethod(request)) { 436 allowedMethods.addAll(mappingInfo.methodNames()); 437 } 438 break; 439 } 440 } 441 } 442 mappingInfo.sortMatchedPatterns(pathComparator); 443 } else if (useTypeLevelMapping(request)) { 444 String[] typeLevelPatterns = getTypeLevelMapping().value(); 445 for (String typeLevelPattern : typeLevelPatterns) { 446 if (!typeLevelPattern.startsWith("/")) { 447 typeLevelPattern = "/" + typeLevelPattern; 448 } 449 boolean useSuffixPattern = useSuffixPattern(request); 450 if (getMatchingPattern(typeLevelPattern, lookupPath, useSuffixPattern) != null) { 451 if (mappingInfo.matches(request)) { 452 match = true; 453 mappingInfo.addMatchedPattern(typeLevelPattern); 454 } else { 455 if (!mappingInfo.matchesRequestMethod(request)) { 456 allowedMethods.addAll(mappingInfo.methodNames()); 457 } 458 break; 459 } 460 } 461 } 462 mappingInfo.sortMatchedPatterns(pathComparator); 463 } else { 464 // No paths specified: parameter match sufficient. 465 match = mappingInfo.matches(request); 466 if (match && mappingInfo.getMethodCount() == 0 && mappingInfo.getParamCount() == 0 467 && resolvedMethodName != null && !resolvedMethodName.equals(handlerMethod.getName())) { 468 match = false; 469 } else { 470 if (!mappingInfo.matchesRequestMethod(request)) { 471 allowedMethods.addAll(mappingInfo.methodNames()); 472 } 473 } 474 } 475 if (match) { 476 Method oldMappedMethod = targetHandlerMethods.put(mappingInfo, handlerMethod); 477 if (oldMappedMethod != null && oldMappedMethod != handlerMethod) { 478 if (methodNameResolver != null && !mappingInfo.hasPatterns()) { 479 if (!oldMappedMethod.getName().equals(handlerMethod.getName())) { 480 if (resolvedMethodName == null) { 481 resolvedMethodName = methodNameResolver.getHandlerMethodName(request); 482 } 483 if (!resolvedMethodName.equals(oldMappedMethod.getName())) { 484 oldMappedMethod = null; 485 } 486 if (!resolvedMethodName.equals(handlerMethod.getName())) { 487 if (oldMappedMethod != null) { 488 targetHandlerMethods.put(mappingInfo, oldMappedMethod); 489 oldMappedMethod = null; 490 } else { 491 targetHandlerMethods.remove(mappingInfo); 492 } 493 } 494 } 495 } 496 if (oldMappedMethod != null) { 497 throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" 498 + lookupPath + "': {" + oldMappedMethod + ", " + handlerMethod 499 + "}. If you intend to handle the same path in multiple methods, then factor " 500 + "them out into a dedicated handler class with that path mapped at the type level!"); 501 } 502 } 503 } 504 } 505 if (!targetHandlerMethods.isEmpty()) { 506 List<RequestSpecificMappingInfo> matches = new ArrayList<RequestSpecificMappingInfo>( 507 targetHandlerMethods.keySet()); 508 RequestSpecificMappingInfoComparator requestMappingInfoComparator = new RequestSpecificMappingInfoComparator( 509 pathComparator, request); 510 Collections.sort(matches, requestMappingInfoComparator); 511 RequestSpecificMappingInfo bestMappingMatch = matches.get(0); 512 String bestMatchedPath = bestMappingMatch.bestMatchedPattern(); 513 if (bestMatchedPath != null) { 514 extractHandlerMethodUriTemplates(bestMatchedPath, lookupPath, request); 515 } 516 return targetHandlerMethods.get(bestMappingMatch); 517 } else { 518 if (!allowedMethods.isEmpty()) { 519 throw new HttpRequestMethodNotSupportedException(request.getMethod(), 520 StringUtils.toStringArray(allowedMethods)); 521 } 522 throw new org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException( 523 lookupPath, request.getMethod(), request.getParameterMap()); 524 } 525 } 526 527 private boolean useTypeLevelMapping(HttpServletRequest request) { 528 if (!hasTypeLevelMapping() || ObjectUtils.isEmpty(getTypeLevelMapping().value())) { 529 return false; 530 } 531 Object value = request.getAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING); 532 return (value != null) ? (Boolean) value : Boolean.TRUE; 533 } 534 535 final String USE_DEFAULT_SUFFIX_PATTERN = DefaultAnnotationHandlerMapping.class.getName() 536 + ".useDefaultSuffixPattern"; 537 538 private boolean useSuffixPattern(HttpServletRequest request) { 539 Object value = request.getAttribute(USE_DEFAULT_SUFFIX_PATTERN); 540 return (value != null) ? (Boolean) value : Boolean.TRUE; 541 } 542 543 /** 544 * Determines the combined pattern for the given methodLevelPattern and 545 * path. 546 * <p> 547 * Uses the following algorithm: 548 * <ol> 549 * <li>If there is a type-level mapping with path information, it is 550 * {@linkplain PathMatcher#combine(String, String) combined} with the 551 * method-level pattern.</li> 552 * <li>If there is a 553 * {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best 554 * matching pattern} in the request, it is combined with the 555 * method-level pattern.</li> 556 * <li>Otherwise, the method-level pattern is returned.</li> 557 * </ol> 558 */ 559 private String getCombinedPattern(String methodLevelPattern, String lookupPath, HttpServletRequest request) { 560 boolean useSuffixPattern = useSuffixPattern(request); 561 if (useTypeLevelMapping(request)) { 562 String[] typeLevelPatterns = getTypeLevelMapping().value(); 563 for (String typeLevelPattern : typeLevelPatterns) { 564 if (!typeLevelPattern.startsWith("/")) { 565 typeLevelPattern = "/" + typeLevelPattern; 566 } 567 String combinedPattern = pathMatcher.combine(typeLevelPattern, methodLevelPattern); 568 String matchingPattern = getMatchingPattern(combinedPattern, lookupPath, useSuffixPattern); 569 if (matchingPattern != null) { 570 return matchingPattern; 571 } 572 } 573 return null; 574 } 575 String bestMatchingPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); 576 if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) { 577 String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern); 578 String matchingPattern = getMatchingPattern(combinedPattern, lookupPath, useSuffixPattern); 579 if (matchingPattern != null && !matchingPattern.equals(bestMatchingPattern)) { 580 return matchingPattern; 581 } 582 } 583 return getMatchingPattern(methodLevelPattern, lookupPath, useSuffixPattern); 584 } 585 586 private String getMatchingPattern(String pattern, String lookupPath, boolean useSuffixPattern) { 587 if (pattern.equals(lookupPath)) { 588 return pattern; 589 } 590 boolean hasSuffix = pattern.indexOf('.') != -1; 591 if (useSuffixPattern && !hasSuffix) { 592 String patternWithSuffix = pattern + ".*"; 593 if (pathMatcher.match(patternWithSuffix, lookupPath)) { 594 return patternWithSuffix; 595 } 596 } 597 if (pathMatcher.match(pattern, lookupPath)) { 598 return pattern; 599 } 600 boolean endsWithSlash = pattern.endsWith("/"); 601 if (useSuffixPattern && !endsWithSlash) { 602 String patternWithSlash = pattern + "/"; 603 if (pathMatcher.match(patternWithSlash, lookupPath)) { 604 return patternWithSlash; 605 } 606 } 607 return null; 608 } 609 610 @SuppressWarnings("unchecked") 611 private void extractHandlerMethodUriTemplates(String mappedPattern, String lookupPath, 612 HttpServletRequest request) { 613 Map<String, String> variables = (Map<String, String>) request 614 .getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); 615 int patternVariableCount = StringUtils.countOccurrencesOf(mappedPattern, "{"); 616 if ((variables == null || patternVariableCount != variables.size()) 617 && pathMatcher.match(mappedPattern, lookupPath)) { 618 variables = pathMatcher.extractUriTemplateVariables(mappedPattern, lookupPath); 619 Map<String, String> decodedVariables = urlPathHelper.decodePathVariables(request, variables); 620 request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, decodedVariables); 621 } 622 } 623 } 624 625 /** 626 * Build a HandlerMethodResolver for the given handler type. 627 */ 628 private ServletHandlerMethodResolver getMethodResolver(Object handler) { 629 Class<?> handlerClass = ClassUtils.getUserClass(handler); 630 ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass); 631 if (resolver == null) { 632 synchronized (this.methodResolverCache) { 633 resolver = this.methodResolverCache.get(handlerClass); 634 if (resolver == null) { 635 resolver = new ServletHandlerMethodResolver(handlerClass); 636 this.methodResolverCache.put(handlerClass, resolver); 637 } 638 } 639 } 640 return resolver; 641 }
调用我们搬出来的代码
至此已成功获取到我们需要的请求映射的具体方法.
注意:如果使用RequestMappingHandlerAdapter已经不需要这么繁琐了.spring已经意识到有人需要得到具体调用的方法,
Spring MVC 3.1开始
所以拦截器的入参类型已经是HandlerMethod.本文只是针对旧版本的的spring框架适用.
This enables some new possibilities. For once a HandlerInterceptor
or a HandlerExceptionResolver
can now expect the Object-based handler to be aHandlerMethod
, which allows them to examine the exact method, its parameters and associated annotations.