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,並且添加了攔截器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM