spring mvc,框架实现权限控制


需求:客户代理的每个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     }
View Code

调用我们搬出来的代码

至此已成功获取到我们需要的请求映射的具体方法.

 注意:如果使用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. 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM