springMVC源码分析--AbstractUrlHandlerMapping(三)

来源:互联网 发布:战地4优化 编辑:程序博客网 时间:2024/05/13 03:54

上一篇博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMapping了,接下来我们介绍其子类AbstractUrlHandlerMapping。


在上一篇博客中我们了解到AbstractHandlerMapping提供了一个抽象类getHandlerInternal(HttpServletRequest request),我们首先看看AbstractUrlHandlerMapping中对抽象类getHandlerInternal(HttpServletRequest request)的实现。

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. //获取Handler,主要是通过url和method的对应关系来查找  
  2.     @Override  
  3.     protected Object getHandlerInternal(HttpServletRequest request) throws Exception {  
  4.         //获取request中的请求链接  
  5.         String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);  
  6.         //根据链接查找handler  
  7.         Object handler = lookupHandler(lookupPath, request);  
  8.         if (handler == null) {  
  9.             // We need to care for the default handler directly, since we need to  
  10.             // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.  
  11.             //定义一个变量,保存找到的原始Handler  
  12.             Object rawHandler = null;  
  13.             if ("/".equals(lookupPath)) {  
  14.                 rawHandler = getRootHandler();  
  15.             }  
  16.             if (rawHandler == null) {  
  17.                 rawHandler = getDefaultHandler();  
  18.             }  
  19.             if (rawHandler != null) {  
  20.                 // Bean name or resolved handler?  
  21.                 //如果是String类型则到容器中查找具体的Bean  
  22.                 if (rawHandler instanceof String) {  
  23.                     String handlerName = (String) rawHandler;  
  24.                     rawHandler = getApplicationContext().getBean(handlerName);  
  25.                 }  
  26.                 validateHandler(rawHandler, request);  
  27.                 handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);  
  28.             }  
  29.         }  
  30.         if (handler != null && logger.isDebugEnabled()) {  
  31.             logger.debug("Mapping [" + lookupPath + "] to " + handler);  
  32.         }  
  33.         else if (handler == null && logger.isTraceEnabled()) {  
  34.             logger.trace("No handler mapping found for [" + lookupPath + "]");  
  35.         }  
  36.         return handler;  
  37.     }  
从上面的实现方法getHandlerInternal来看,首先是通过lookupHandler方法来查找Handler,这里我们看到了之前说的Map对象,用来存储url和Handler之间的关系,当Handler获取为String时需要从Bean容器中获取注入的实现类,当然在查找过程中也会有模糊匹配等查找过程。

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {  
  2.         // Direct match?  
  3.         //直接从map中获取  
  4.         Object handler = this.handlerMap.get(urlPath);  
  5.         if (handler != null) {  
  6.             // Bean name or resolved handler?  
  7.             //如果是String类型则从容器中获取  
  8.             if (handler instanceof String) {  
  9.                 String handlerName = (String) handler;  
  10.                 handler = getApplicationContext().getBean(handlerName);  
  11.             }  
  12.             validateHandler(handler, request);  
  13.             return buildPathExposingHandler(handler, urlPath, urlPath, null);  
  14.         }  
  15.         // Pattern match?  
  16.         //通过模糊匹配来查找  
  17.         List<String> matchingPatterns = new ArrayList<String>();  
  18.         for (String registeredPattern : this.handlerMap.keySet()) {  
  19.             if (getPathMatcher().match(registeredPattern, urlPath)) {  
  20.                 matchingPatterns.add(registeredPattern);  
  21.             }  
  22.             else if (useTrailingSlashMatch()) {  
  23.                 if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {  
  24.                     matchingPatterns.add(registeredPattern +"/");  
  25.                 }  
  26.             }  
  27.         }  
  28.         String bestPatternMatch = null;  
  29.         //匹配规则  
  30.         Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);  
  31.         if (!matchingPatterns.isEmpty()) {  
  32.             Collections.sort(matchingPatterns, patternComparator);  
  33.             if (logger.isDebugEnabled()) {  
  34.                 logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);  
  35.             }  
  36.             bestPatternMatch = matchingPatterns.get(0);  
  37.         }  
  38.         if (bestPatternMatch != null) {  
  39.             handler = this.handlerMap.get(bestPatternMatch);  
  40.             if (handler == null) {  
  41.                 Assert.isTrue(bestPatternMatch.endsWith("/"));  
  42.                 handler = this.handlerMap.get(bestPatternMatch.substring(0, bestPatternMatch.length() - 1));  
  43.             }  
  44.             // Bean name or resolved handler?  
  45.             if (handler instanceof String) {  
  46.                 String handlerName = (String) handler;  
  47.                 handler = getApplicationContext().getBean(handlerName);  
  48.             }  
  49.             validateHandler(handler, request);  
  50.             String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);  
  51.   
  52.             // There might be multiple 'best patterns', let's make sure we have the correct URI template variables  
  53.             // for all of them  
  54.             Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();  
  55.             for (String matchingPattern : matchingPatterns) {  
  56.                 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {  
  57.                     Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);  
  58.                     Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);  
  59.                     uriTemplateVariables.putAll(decodedVars);  
  60.                 }  
  61.             }  
  62.             if (logger.isDebugEnabled()) {  
  63.                 logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);  
  64.             }  
  65.             return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);  
  66.         }  
  67.         // No handler found...  
  68.         return null;  
  69.     }  

上面两个方法介绍了通过url来查找handlerMap获取handler的操作,AbstractUrlHandlerMapping中也提供了注册url和handler到handlerMap中的操作,具体的调用则要到AbstractUrlHandlerMapping的子类中实现。

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. //注册url和Bean的map,注册多个string的url到一个处理器中  
  2.     protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {  
  3.         Assert.notNull(urlPaths, "URL path array must not be null");  
  4.         for (String urlPath : urlPaths) {  
  5.             registerHandler(urlPath, beanName);  
  6.         }  
  7.     }  
  8.       
  9.     ////注册url和Bean的map,将具体的Handler注入到url对应的map中  
  10.     protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {  
  11.         Assert.notNull(urlPath, "URL path must not be null");  
  12.         Assert.notNull(handler, "Handler object must not be null");  
  13.         Object resolvedHandler = handler;  
  14.   
  15.         // Eagerly resolve handler if referencing singleton via name.  
  16.         //如果Handler是String类型而且没有设置lazyInitHandlers则从springMVC容器中获取handler  
  17.         if (!this.lazyInitHandlers && handler instanceof String) {  
  18.             String handlerName = (String) handler;  
  19.             if (getApplicationContext().isSingleton(handlerName)) {  
  20.                 resolvedHandler = getApplicationContext().getBean(handlerName);  
  21.             }  
  22.         }  
  23.   
  24.         Object mappedHandler = this.handlerMap.get(urlPath);  
  25.         if (mappedHandler != null) {  
  26.             if (mappedHandler != resolvedHandler) {  
  27.                 throw new IllegalStateException(  
  28.                         "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +  
  29.                         "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");  
  30.             }  
  31.         }  
  32.         else {  
  33.             if (urlPath.equals("/")) {  
  34.                 if (logger.isInfoEnabled()) {  
  35.                     logger.info("Root mapping to " + getHandlerDescription(handler));  
  36.                 }  
  37.                 setRootHandler(resolvedHandler);  
  38.             }  
  39.             else if (urlPath.equals("/*")) {  
  40.                 if (logger.isInfoEnabled()) {  
  41.                     logger.info("Default mapping to " + getHandlerDescription(handler));  
  42.                 }  
  43.                 setDefaultHandler(resolvedHandler);  
  44.             }  
  45.             else {  
  46.                 this.handlerMap.put(urlPath, resolvedHandler);  
  47.                 if (logger.isInfoEnabled()) {  
  48.                     logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));  
  49.                 }  
  50.             }  
  51.         }  
  52.     }  
通过上面介绍我们知道AbstractUrlHandlerMapping提供的功能就是根据url从handlerMap中获取handler和注册url和handler的对应关系到handlerMap中,当然这个过程中还包含很多其他的操作。

AbstractUrlHandlerMapping的完整源码如下:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {  
  2.   
  3.     private Object rootHandler;  
  4.   
  5.     private boolean useTrailingSlashMatch = false;  
  6.   
  7.     private boolean lazyInitHandlers = false;  
  8.   
  9.     private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();  
  10.   
  11.     public void setRootHandler(Object rootHandler) {  
  12.         this.rootHandler = rootHandler;  
  13.     }  
  14.   
  15.     public Object getRootHandler() {  
  16.         return this.rootHandler;  
  17.     }  
  18.   
  19.     public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) {  
  20.         this.useTrailingSlashMatch = useTrailingSlashMatch;  
  21.     }  
  22.   
  23.     public boolean useTrailingSlashMatch() {  
  24.         return this.useTrailingSlashMatch;  
  25.     }  
  26.   
  27.     public void setLazyInitHandlers(boolean lazyInitHandlers) {  
  28.         this.lazyInitHandlers = lazyInitHandlers;  
  29.     }  
  30.       
  31.     //获取Handler,主要是通过url和method的对应关系来查找  
  32.     @Override  
  33.     protected Object getHandlerInternal(HttpServletRequest request) throws Exception {  
  34.         //获取request中的请求链接  
  35.         String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);  
  36.         //根据链接查找handler  
  37.         Object handler = lookupHandler(lookupPath, request);  
  38.         if (handler == null) {  
  39.             // We need to care for the default handler directly, since we need to  
  40.             // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.  
  41.             //定义一个变量,保存找到的原始Handler  
  42.             Object rawHandler = null;  
  43.             if ("/".equals(lookupPath)) {  
  44.                 rawHandler = getRootHandler();  
  45.             }  
  46.             if (rawHandler == null) {  
  47.                 rawHandler = getDefaultHandler();  
  48.             }  
  49.             if (rawHandler != null) {  
  50.                 // Bean name or resolved handler?  
  51.                 //如果是String类型则到容器中查找具体的Bean  
  52.                 if (rawHandler instanceof String) {  
  53.                     String handlerName = (String) rawHandler;  
  54.                     rawHandler = getApplicationContext().getBean(handlerName);  
  55.                 }  
  56.                 validateHandler(rawHandler, request);  
  57.                 handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);  
  58.             }  
  59.         }  
  60.         if (handler != null && logger.isDebugEnabled()) {  
  61.             logger.debug("Mapping [" + lookupPath + "] to " + handler);  
  62.         }  
  63.         else if (handler == null && logger.isTraceEnabled()) {  
  64.             logger.trace("No handler mapping found for [" + lookupPath + "]");  
  65.         }  
  66.         return handler;  
  67.     }  
  68.       
  69.     protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {  
  70.         // Direct match?  
  71.         //直接从map中获取  
  72.         Object handler = this.handlerMap.get(urlPath);  
  73.         if (handler != null) {  
  74.             // Bean name or resolved handler?  
  75.             //如果是String类型则从容器中获取  
  76.             if (handler instanceof String) {  
  77.                 String handlerName = (String) handler;  
  78.                 handler = getApplicationContext().getBean(handlerName);  
  79.             }  
  80.             validateHandler(handler, request);  
  81.             return buildPathExposingHandler(handler, urlPath, urlPath, null);  
  82.         }  
  83.         // Pattern match?  
  84.         //通过模糊匹配来查找  
  85.         List<String> matchingPatterns = new ArrayList<String>();  
  86.         for (String registeredPattern : this.handlerMap.keySet()) {  
  87.             if (getPathMatcher().match(registeredPattern, urlPath)) {  
  88.                 matchingPatterns.add(registeredPattern);  
  89.             }  
  90.             else if (useTrailingSlashMatch()) {  
  91.                 if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {  
  92.                     matchingPatterns.add(registeredPattern +"/");  
  93.                 }  
  94.             }  
  95.         }  
  96.         String bestPatternMatch = null;  
  97.         //匹配规则  
  98.         Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);  
  99.         if (!matchingPatterns.isEmpty()) {  
  100.             Collections.sort(matchingPatterns, patternComparator);  
  101.             if (logger.isDebugEnabled()) {  
  102.                 logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);  
  103.             }  
  104.             bestPatternMatch = matchingPatterns.get(0);  
  105.         }  
  106.         if (bestPatternMatch != null) {  
  107.             handler = this.handlerMap.get(bestPatternMatch);  
  108.             if (handler == null) {  
  109.                 Assert.isTrue(bestPatternMatch.endsWith("/"));  
  110.                 handler = this.handlerMap.get(bestPatternMatch.substring(0, bestPatternMatch.length() - 1));  
  111.             }  
  112.             // Bean name or resolved handler?  
  113.             if (handler instanceof String) {  
  114.                 String handlerName = (String) handler;  
  115.                 handler = getApplicationContext().getBean(handlerName);  
  116.             }  
  117.             validateHandler(handler, request);  
  118.             String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);  
  119.   
  120.             // There might be multiple 'best patterns', let's make sure we have the correct URI template variables  
  121.             // for all of them  
  122.             Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();  
  123.             for (String matchingPattern : matchingPatterns) {  
  124.                 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {  
  125.                     Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);  
  126.                     Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);  
  127.                     uriTemplateVariables.putAll(decodedVars);  
  128.                 }  
  129.             }  
  130.             if (logger.isDebugEnabled()) {  
  131.                 logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);  
  132.             }  
  133.             return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);  
  134.         }  
  135.         // No handler found...  
  136.         return null;  
  137.     }  
  138.   
  139.     protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {  
  140.     }  
  141.   
  142.     //用于给找到的Handler注册两个拦截器PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor  
  143.     //这两个拦截器的的作用是将与当前url实际匹配的Pattern、匹配条件和url模板参数设置到request的属性中  
  144.     protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,  
  145.             String pathWithinMapping, Map<String, String> uriTemplateVariables) {  
  146.   
  147.         HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);  
  148.         chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));  
  149.         if (!CollectionUtils.isEmpty(uriTemplateVariables)) {  
  150.             chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));  
  151.         }  
  152.         return chain;  
  153.     }  
  154.   
  155.     protected void exposePathWithinMapping(String bestMatchingPattern, String pathWithinMapping, HttpServletRequest request) {  
  156.         request.setAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatchingPattern);  
  157.         request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);  
  158.     }  
  159.   
  160.     protected void exposeUriTemplateVariables(Map<String, String> uriTemplateVariables, HttpServletRequest request) {  
  161.         request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);  
  162.     }  
  163.       
  164.     //注册url和Bean的map,注册多个string的url到一个处理器中  
  165.     protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {  
  166.         Assert.notNull(urlPaths, "URL path array must not be null");  
  167.         for (String urlPath : urlPaths) {  
  168.             registerHandler(urlPath, beanName);  
  169.         }  
  170.     }  
  171.       
  172.     ////注册url和Bean的map,将具体的Handler注入到url对应的map中  
  173.     protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {  
  174.         Assert.notNull(urlPath, "URL path must not be null");  
  175.         Assert.notNull(handler, "Handler object must not be null");  
  176.         Object resolvedHandler = handler;  
  177.   
  178.         // Eagerly resolve handler if referencing singleton via name.  
  179.         //如果Handler是String类型而且没有设置lazyInitHandlers则从springMVC容器中获取handler  
  180.         if (!this.lazyInitHandlers && handler instanceof String) {  
  181.             String handlerName = (String) handler;  
  182.             if (getApplicationContext().isSingleton(handlerName)) {  
  183.                 resolvedHandler = getApplicationContext().getBean(handlerName);  
  184.             }  
  185.         }  
  186.   
  187.         Object mappedHandler = this.handlerMap.get(urlPath);  
  188.         if (mappedHandler != null) {  
  189.             if (mappedHandler != resolvedHandler) {  
  190.                 throw new IllegalStateException(  
  191.                         "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +  
  192.                         "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");  
  193.             }  
  194.         }  
  195.         else {  
  196.             if (urlPath.equals("/")) {  
  197.                 if (logger.isInfoEnabled()) {  
  198.                     logger.info("Root mapping to " + getHandlerDescription(handler));  
  199.                 }  
  200.                 setRootHandler(resolvedHandler);  
  201.             }  
  202.             else if (urlPath.equals("/*")) {  
  203.                 if (logger.isInfoEnabled()) {  
  204.                     logger.info("Default mapping to " + getHandlerDescription(handler));  
  205.                 }  
  206.                 setDefaultHandler(resolvedHandler);  
  207.             }  
  208.             else {  
  209.                 this.handlerMap.put(urlPath, resolvedHandler);  
  210.                 if (logger.isInfoEnabled()) {  
  211.                     logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));  
  212.                 }  
  213.             }  
  214.         }  
  215.     }  
  216.   
  217.     private String getHandlerDescription(Object handler) {  
  218.         return "handler " + (handler instanceof String ? "'" + handler + "'" : "of type [" + handler.getClass() + "]");  
  219.     }  
  220.   
  221.     public final Map<String, Object> getHandlerMap() {  
  222.         return Collections.unmodifiableMap(this.handlerMap);  
  223.     }  
  224.   
  225.     protected boolean supportsTypeLevelMappings() {  
  226.         return false;  
  227.     }  
  228.   
  229.     private class PathExposingHandlerInterceptor extends HandlerInterceptorAdapter {  
  230.   
  231.         private final String bestMatchingPattern;  
  232.   
  233.         private final String pathWithinMapping;  
  234.   
  235.         public PathExposingHandlerInterceptor(String bestMatchingPattern, String pathWithinMapping) {  
  236.             this.bestMatchingPattern = bestMatchingPattern;  
  237.             this.pathWithinMapping = pathWithinMapping;  
  238.         }  
  239.   
  240.         @Override  
  241.         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {  
  242.             exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request);  
  243.             request.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings());  
  244.             return true;  
  245.         }  
  246.   
  247.     }  
  248.       
  249.     private class UriTemplateVariablesHandlerInterceptor extends HandlerInterceptorAdapter {  
  250.   
  251.         private final Map<String, String> uriTemplateVariables;  
  252.   
  253.         public UriTemplateVariablesHandlerInterceptor(Map<String, String> uriTemplateVariables) {  
  254.             this.uriTemplateVariables = uriTemplateVariables;  
  255.         }  
  256.   
  257.         @Override  
  258.         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {  
  259.             exposeUriTemplateVariables(this.uriTemplateVariables, request);  
  260.             return true;  
  261.         }  
  262.     }  
  263.   
  264. }
0 0