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

本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说。

大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入doDispatch()方法,这个是完成请求的方法.

今天我们只分析:mappedHandler = this.getHandler(processedRequest, false); 这一个方法;

 1     protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
 2         Iterator i$ = this.handlerMappings.iterator();//handlerMapping 是初始化的时候就保存好的,如果多个的话已经排序好了
 3 
 4         HandlerExecutionChain handler; //实际上返回的handler是一个 handler链,包含了处理器和拦截器
 5         do {
 6             if (!i$.hasNext()) {
 7                 return null;
 8             }
 9             //这块发现实际上就是取第一个就好了
10             HandlerMapping hm = (HandlerMapping)i$.next();
11             if (this.logger.isTraceEnabled()) {
12                 this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
13             }
14 
15             handler = hm.getHandler(request); //然后调用具体处理器的getHandler方法
16         } while(handler == null);
17 
18         return handler;
19     }

现在以BeanNameUrlHandlerMapping为例:

这个类的继承关系前面几篇文章已经介绍过了。实际上父类AbstractHandlerMapping实现了gethandler方法,还记得这个类初始化的时候做的是初始化拦截器,然后让子类重写方法initApplicationContext进行处理注册 

 1     public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
 2         Object handler = this.getHandlerInternal(request);//钩子方法,让子类自己去实现,查找处理器的逻辑
 3         if (handler == null) {
 4             handler = this.getDefaultHandler();
 5         }
 6 
 7         if (handler == null) {
 8             return null;
 9         } else {
10             if (handler instanceof String) {
11                 String handlerName = (String)handler;
12                 handler = this.getApplicationContext().getBean(handlerName);
13             }
14 
15             return this.getHandlerExecutionChain(handler, request);//封装 处理器链
16         }
17     }
getHandlerInternal是由AbstractUrlHandlerMapping实现的, 他是BeanNameUrlHandlerMapping和SimpleUrlHandlerMapping的父类,所以,两个映射器都是通过这个方法查找的,
 1     protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
 2         String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); //从请求中获取URL
 3         Object handler = this.lookupHandler(lookupPath, request); //查找handler
 4         if (handler == null) { //如果没找到 给一个默认的处理器
 5             Object rawHandler = null; 
 6             if ("/".equals(lookupPath)) {
 7                 rawHandler = this.getRootHandler();
 8             }
 9 
10             if (rawHandler == null) {
11                 rawHandler = this.getDefaultHandler();
12             }
13 
14             if (rawHandler != null) {
15                 if (rawHandler instanceof String) {
16                     String handlerName = (String)rawHandler;
17                     rawHandler = this.getApplicationContext().getBean(handlerName);
18                 }
19 
20                 this.validateHandler(rawHandler, request);
21                 handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null);//添加两个拦截器,作用?
22             }
23         }
24 
25         if (handler != null && this.logger.isDebugEnabled()) {
26             this.logger.debug("Mapping [" + lookupPath + "] to " + handler);
27         } else if (handler == null && this.logger.isTraceEnabled()) {
28             this.logger.trace("No handler mapping found for [" + lookupPath + "]");
29         }
30 
31         return handler;
32     }
 1     protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
 2         Object handler = this.handlerMap.get(urlPath); //直接从map中获取
 3         if (handler != null) {
 4             if (handler instanceof String) {
 5                 String handlerName = (String)handler;
 6                 handler = this.getApplicationContext().getBean(handlerName);
 7             }
 8 
 9             this.validateHandler(handler, request);
10             return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);//添加拦截器
11         } else {
12             List<String> matchingPatterns = new ArrayList(); //如果没找到就遍历所有的map的url,进行匹配
13             Iterator i$ = this.handlerMap.keySet().iterator();
14 
15             while(i$.hasNext()) {
16                 String registeredPattern = (String)i$.next();
17                 if (this.getPathMatcher().match(registeredPattern, urlPath)) {
18                     matchingPatterns.add(registeredPattern);
19                 }
20             }
21 
22             String bestPatternMatch = null;
23             Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
24             if (!matchingPatterns.isEmpty()) {
25                 Collections.sort(matchingPatterns, patternComparator);
26                 if (this.logger.isDebugEnabled()) {
27                     this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
28                 }
29 
30                 bestPatternMatch = (String)matchingPatterns.get(0); //如果有匹配的上的,取第一个
31             }
32 
33             if (bestPatternMatch != null) {
34                 handler = this.handlerMap.get(bestPatternMatch);
35                 String pathWithinMapping;
36                 if (handler instanceof String) {
37                     pathWithinMapping = (String)handler;
38                     handler = this.getApplicationContext().getBean(pathWithinMapping);
39                 }
40 
41                 this.validateHandler(handler, request);
42                 pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
43                 Map<String, String> uriTemplateVariables = new LinkedHashMap();
44                 Iterator i$ = matchingPatterns.iterator();
45 
46                 while(i$.hasNext()) {
47                     String matchingPattern = (String)i$.next();
48                     if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
49                         Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
50                         Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
51                         uriTemplateVariables.putAll(decodedVars);
52                     }
53                 }
54 
55                 if (this.logger.isDebugEnabled()) {
56                     this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
57                 }
58 
59                 return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
60             } else {
61                 return null;
62             }
63         }
64     }
到此为止就找到了handler,并且添加了拦截器
原文地址:https://www.cnblogs.com/haoerlv/p/8670003.html