第三章 SpringMVC之HandlerMapping解析

         HandlerMapping的作用就是解析请求链接,然后根据请求链接找到执行这个请求的类(HandlerMapping所说的handler,也就是我们写的Controller或是Action)。至于我们在配置文件中配置的BeanNameUrlHandlerMapping或者是SimpleUrlHandlerMapping,他们的目的是一样的,只是通过请求链接来找handler的方式不一样罢了。先借网上的一张图来说明HandlerMapping相关类之间的关系

HandlerMapping核心类图

        HandlerMapping的使用主要分为两步:注册和查找。

        注册是根据配置文件中的配置将一个字符串和一个Controller类以<key,value>的形式存入到Map中,这个key就是对应的url中的某个字段。

        查找就是HandlerMapping根据url中的的某个字段,在Map中以这个字段为key值对应的Controller类,并将Controller类封装成一个HandlerExecutionChain对象,HandlerExecutionChain中除了有Controller对象外,还有一组拦截器。

        这里将以SimpleUrlHandlerMapping为例子来分析HandlerMapping是如何根据请求链接找到Controller类的。

         一.注册

          SpringMVC中的HandlerMapping配置       

  1.       <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  2.              <property name="mappings">  
  3.                           <span style="background-color: rgb(255, 0, 0);"><props>  
  4.                                  <prop key="/springMVC.d">/HelloWorld</prop>  
  5.                           </props></span>  
  6.              </property>  
  7. </bean>  
  8.       
  9. <bean name="/HelloWorld" class="com.wangbiao.springMVC.HelloWorld">  
  10.              <property name="methodNameResolver">  
  11.                            <ref local="methodNameResolver"/>  
  12.              </property>  
  13. </bean>  
当我们第一次访问服务器的时候IOC容器会根据配置文件中的红色的部分生成一个Map<String, Object>,这个map里面的值就是{/springMVC.d=/HelloWorld}。

SimpleUrlHandlerMapping的作用就是获取这个集合,然后根据这个集合里的value找到对应的bean,这样就可以把url中的某个字段和我们写的处理器对应起来。下面是SimpleUrlHandlerMapping中的关键源码

  1. public void initApplicationContext() throws BeansException {  
  2.         super.initApplicationContext();  
  3.         registerHandlers(this.urlMap);  
  4. }  
这个方法就是初始化SpringMVC容器,并对handler进行注册,urlMap中的值根据上面的配置文件就是{/springMVC.d=/HelloWorld},下面再看看registerHandlers方法
  1. protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {  
  2.         if (urlMap.isEmpty()) {  
  3.             logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");  
  4.         }  
  5.         else {  
  6.             for (Map.Entry<String, Object> entry : urlMap.entrySet()) {  
  7.                 String url = entry.getKey();  
  8.                 Object handler = entry.getValue();  
  9.                 // Prepend with slash if not already present.  
  10.                 if (!url.startsWith("/")) {  
  11.                     url = "/" + url;  
  12.                 }  
  13.                 // Remove whitespace from handler bean name.  
  14.                 if (handler instanceof String) {  
  15.                     handler = ((String) handler).trim();  
  16.                 }  
  17.                 <span style="color:#ff0000;">registerHandler(url, handler);</span>  
  18.             }  
  19.         }  
  20.     }  
主要是对urlMap中的key值进行了一些处理,要是没有“/”的就加上"/",去掉空格等处理。这个方法中的重点是调用了registerHandler(url, handler)这个方法,在这个方法是它的父类
AbstractUrlHandlerMapping中的方法,我们来看看AbstractUrlHandlerMapping中的registerHandler(url, handler)
  1. protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {  
  2.     Assert.notNull(urlPath, "URL path must not be null");  
  3.     Assert.notNull(handler, "Handler object must not be null");  
  4.     Object resolvedHandler = handler;  
  5.   
  6.     // Eagerly resolve handler if referencing singleton via name.  
  7.     if (!this.lazyInitHandlers && handler instanceof String) {  
  8.         String handlerName = (String) handler;  
  9.         if (getApplicationContext().isSingleton(handlerName)) {  
  10.             <span style="background-color: rgb(255, 255, 255);"><span style="color:#ff0000;">resolvedHandler = getApplicationContext().getBean(handlerName);</span></span>  
  11.         }  
  12.     }  
  13.   
  14.     Object mappedHandler = this.handlerMap.get(urlPath);  
  15.     if (mappedHandler != null) {  
  16.         if (mappedHandler != resolvedHandler) {  
  17.             throw new IllegalStateException(  
  18.                     "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +  
  19.                     "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");  
  20.         }  
  21.     }  
  22.     else {  
  23.         if (urlPath.equals("/")) {  
  24.             if (logger.isInfoEnabled()) {  
  25.                 logger.info("Root mapping to " + getHandlerDescription(handler));  
  26.             }  
  27.             setRootHandler(resolvedHandler);  
  28.         }  
  29.         else if (urlPath.equals("/*")) {  
  30.             if (logger.isInfoEnabled()) {  
  31.                 logger.info("Default mapping to " + getHandlerDescription(handler));  
  32.             }  
  33.             setDefaultHandler(resolvedHandler);  
  34.         }  
  35.         else {  
  36.             <span style="color:#ff0000;">this.handlerMap.put(urlPath, resolvedHandler);</span>  
  37.             if (logger.isInfoEnabled()) {  
  38.                 logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));  
  39.             }  
  40.         }  
  41.     }  
  42. }  
看registerHandler方法红色的部分大家,可以看出是根据SimpleUrlHandlerMapping中的urlMap中的value值在ioc容器中找到对应的bean,并将url的某个字段作为key值,bean作为value存入到AbstractUrlHandlerMapping的urlMap属性中去,这样就达到url的某个字段对应到具体的controller了的目的,当遇到有请求访问服务器的时候,就可以根据url找到具体的controller去执行这个请求了。

          二.查找
           在Dispatcher类中,根据配置文件对handlerMapping进行注册,即对handlerMapping的初始化。

            

  1.      protected void initStrategies(ApplicationContext context) {  
  2. initMultipartResolver(context);  
  3. initLocaleResolver(context);  
  4. initThemeResolver(context);  
  5. <span style="color:#ff0000;">initHandlerMappings(context);</span>  
  6. initHandlerAdapters(context);  
  7. initHandlerExceptionResolvers(context);  
  8. initRequestToViewNameTranslator(context);  
  9. initViewResolvers(context);  
  1.       private void initHandlerMappings(ApplicationContext context) {  
  2. this.handlerMappings = null;  
  3.   
  4. if (this.detectAllHandlerMappings) {  
  5.     // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.  
  6.     <span style="color:#ff0000;">Map<String, HandlerMapping> matchingBeans =  
  7.             BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.classtruefalse);</span>  
  8.     if (!matchingBeans.isEmpty()) {  
  9.         <span style="color:#ff0000;">this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());</span>  
  10.         // We keep HandlerMappings in sorted order.  
  11.         OrderComparator.sort(this.handlerMappings);  
  12.     }  
  13. }  
  14. else {  
  15.     try {  
  16.         HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);  
  17.         this.handlerMappings = Collections.singletonList(hm);  
  18.     }  
  19.     catch (NoSuchBeanDefinitionException ex) {  
  20.         // Ignore, we'll add a default HandlerMapping later.  
  21.     }  
  22. }  
由于在配置文件中有两种不同类型的handlerMapping,所以从ioc容器中读取出来的handlerMapping有两个,然后将这两个handlerMapping的实例放入Dodispatcher中的handlerMappings属性中。

下面一步就是真正的根据url中的某个字段到已经注册好了的Map<urlString,Controller>中找出执行这个url请求的Controller,用户的请求在被Dispatcher拦截后,会交给Dispatcher的doDispatch执行。在doDispatch方法中主要看红色标记的getHandler方法

  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.         HttpServletRequest processedRequest = request;  
  3.         HandlerExecutionChain mappedHandler = null;  
  4.         int interceptorIndex = -1;  
  5.   
  6.         try {  
  7.             ModelAndView mv;  
  8.             boolean errorView = false;  
  9.   
  10.             try {  
  11.                 processedRequest = checkMultipart(request);  
  12.   
  13.                 // Determine handler for the current request.  
  14.                 <span style="color:#ff0000;">mappedHandler = getHandler(processedRequest, false);</span>  
  15.                 if (mappedHandler == null || mappedHandler.getHandler() == null) {  
  16.                     noHandlerFound(processedRequest, response);  
  17.                     return;  
  18.                 }  
  19.   
  20.                 // Determine handler adapter for the current request.  
  21.                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
  22.   
  23.                 // Process last-modified header, if supported by the handler.  
  24.                 String method = request.getMethod();  
  25.                 boolean isGet = "GET".equals(method);  
  26.                 if (isGet || "HEAD".equals(method)) {  
  27.                     long lastModified = ha.getLastModified(request, mappedHandler.getHandler());  
  28.                     if (logger.isDebugEnabled()) {  
  29.                         String requestUri = urlPathHelper.getRequestUri(request);  
  30.                         logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);  
  31.                     }  
  32.                     if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {  
  33.                         return;  
  34.                     }  
  35.                 }  
  36.   
  37.                 // Apply preHandle methods of registered interceptors.  
  38.                 HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();  
  39.                 if (interceptors != null) {  
  40.                     for (int i = 0; i < interceptors.length; i++) {  
  41.                         HandlerInterceptor interceptor = interceptors[i];  
  42.                         if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {  
  43.                             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
  44.                             return;  
  45.                         }  
  46.                         interceptorIndex = i;  
  47.                     }  
  48.                 }  
  49.   
  50.                 // Actually invoke the handler.  
  51.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  52.   
  53.                 // Do we need view name translation?  
  54.                 if (mv != null && !mv.hasView()) {  
  55.                     mv.setViewName(getDefaultViewName(request));  
  56.                 }  
  57.   
  58.                 // Apply postHandle methods of registered interceptors.  
  59.                 if (interceptors != null) {  
  60.                     for (int i = interceptors.length - 1; i >= 0; i--) {  
  61.                         HandlerInterceptor interceptor = interceptors[i];  
  62.                         interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);  
  63.                     }  
  64.                 }  
  65.             }  
  66.             catch (ModelAndViewDefiningException ex) {  
  67.                 logger.debug("ModelAndViewDefiningException encountered", ex);  
  68.                 mv = ex.getModelAndView();  
  69.             }  
  70.             catch (Exception ex) {  
  71.                 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);  
  72.                 mv = processHandlerException(processedRequest, response, handler, ex);  
  73.                 errorView = (mv != null);  
  74.             }  
  75.   
  76.             // Did the handler return a view to render?  
  77.             if (mv != null && !mv.wasCleared()) {  
  78.                 render(mv, processedRequest, response);  
  79.                 if (errorView) {  
  80.                     WebUtils.clearErrorRequestAttributes(request);  
  81.                 }  
  82.             }  
  83.             else {  
  84.                 if (logger.isDebugEnabled()) {  
  85.                     logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +  
  86.                             "': assuming HandlerAdapter completed request handling");  
  87.                 }  
  88.             }  
  89.   
  90.             // Trigger after-completion for successful outcome.  
  91.             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
  92.         }  

getHandler方法主要会调用已经注册好了的handlerMapping中的getHandler方法

DispatcherServlet中的getHandler方法
  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  
  2.         for (HandlerMapping hm : this.handlerMappings) {  
  3.             if (logger.isTraceEnabled()) {  
  4.                 logger.trace(  
  5.                         "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");  
  6.             }  
  7.             <span style="color:#ff0000;">HandlerExecutionChain handler = hm.getHandler(request);</span>  
  8.             if (handler != null) {  
  9.                 return handler;  
  10.             }  
  11.         }  
  12.         return null;  
  13. }  

在来看看HandlerMapping的getHandler方法,可以看到HandlerMapping接口中只有一个getHandler方法。
  1. /* 
  2.  * Copyright 2002-2007 the original author or authors. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package org.springframework.web.servlet;  
  18.   
  19. import javax.servlet.http.HttpServletRequest;  
  20.   
  21. /** 
  22.  * Interface to be implemented by objects that define a mapping between 
  23.  * requests and handler objects. 
  24.  * 
  25.  * <p>This class can be implemented by application developers, although this is not 
  26.  * necessary, as {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping} 
  27.  * and {@link org.springframework.web.servlet.handler.SimpleUrlHandlerMapping} 
  28.  * are included in the framework. The former is the default if no 
  29.  * HandlerMapping bean is registered in the application context. 
  30.  * 
  31.  * <p>HandlerMapping implementations can support mapped interceptors but do not 
  32.  * have to. A handler will always be wrapped in a {@link HandlerExecutionChain} 
  33.  * instance, optionally accompanied by some {@link HandlerInterceptor} instances. 
  34.  * The DispatcherServlet will first call each HandlerInterceptor's 
  35.  * <code>preHandle</code> method in the given order, finally invoking the handler 
  36.  * itself if all <code>preHandle</code> methods have returned <code>true</code>. 
  37.  * 
  38.  * <p>The ability to parameterize this mapping is a powerful and unusual 
  39.  * capability of this MVC framework. For example, it is possible to write 
  40.  * a custom mapping based on session state, cookie state or many other 
  41.  * variables. No other MVC framework seems to be equally flexible. 
  42.  * 
  43.  * <p>Note: Implementations can implement the {@link org.springframework.core.Ordered} 
  44.  * interface to be able to specify a sorting order and thus a priority for getting 
  45.  * applied by DispatcherServlet. Non-Ordered instances get treated as lowest priority. 
  46.  * 
  47.  * @author Rod Johnson 
  48.  * @author Juergen Hoeller 
  49.  * @see org.springframework.core.Ordered 
  50.  * @see org.springframework.web.servlet.handler.AbstractHandlerMapping 
  51.  * @see org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping 
  52.  * @see org.springframework.web.servlet.handler.SimpleUrlHandlerMapping 
  53.  */  
  54. public interface HandlerMapping {  
  55.   
  56.     /** 
  57.      * Name of the {@link HttpServletRequest} attribute that contains the path 
  58.      * within the handler mapping, in case of a pattern match, or the full 
  59.      * relevant URI (typically within the DispatcherServlet's mapping) else. 
  60.      * <p>Note: This attribute is not required to be supported by all 
  61.      * HandlerMapping implementations. URL-based HandlerMappings will 
  62.      * typically support it, but handlers should not necessarily expect 
  63.      * this request attribute to be present in all scenarios. 
  64.      */  
  65.     String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";  
  66.   
  67.     /** 
  68.      * Name of the {@link HttpServletRequest} attribute that contains the 
  69.      * best matching pattern within the handler mapping. 
  70.      * <p>Note: This attribute is not required to be supported by all 
  71.      * HandlerMapping implementations. URL-based HandlerMappings will 
  72.      * typically support it, but handlers should not necessarily expect 
  73.      * this request attribute to be present in all scenarios. 
  74.      */  
  75.     String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";  
  76.   
  77.     /** 
  78.      * Name of the {@link HttpServletRequest} attribute that contains the URI 
  79.      * templates map, mapping variable names to values. 
  80.      * <p>Note: This attribute is not required to be supported by all 
  81.      * HandlerMapping implementations. URL-based HandlerMappings will 
  82.      * typically support it, but handlers should not necessarily expect 
  83.      * this request attribute to be present in all scenarios. 
  84.      */  
  85.     String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";  
  86.   
  87.     /** 
  88.      * Return a handler and any interceptors for this request. The choice may be made 
  89.      * on request URL, session state, or any factor the implementing class chooses. 
  90.      * <p>The returned HandlerExecutionChain contains a handler Object, rather than 
  91.      * even a tag interface, so that handlers are not constrained in any way. 
  92.      * For example, a HandlerAdapter could be written to allow another framework's 
  93.      * handler objects to be used. 
  94.      * <p>Returns <code>null</code> if no match was found. This is not an error. 
  95.      * The DispatcherServlet will query all registered HandlerMapping beans to find 
  96.      * a match, and only decide there is an error if none can find a handler. 
  97.      * @param request current HTTP request 
  98.      * @return a HandlerExecutionChain instance containing handler object and 
  99.      * any interceptors, or <code>null</code> if no mapping found 
  100.      * @throws Exception if there is an internal error 
  101.      */  
  102.     HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;  
  103.   
  104. }  
再看看实现了HandlerMapping的AbstractHandlerMapping抽象类,AbstractHandlerMapping中的getHandler方法,这个方法的主要作用是根据url找到controller后,并将controller封装成一个HandlerExecutionChain对象
  1. public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  
  2.         <span style="color:#ff0000;">Object handler = getHandlerInternal(request);</span>  
  3.         if (handler == null) {  
  4.             handler = getDefaultHandler();  
  5.         }  
  6.         if (handler == null) {  
  7.             return null;  
  8.         }  
  9.         // Bean name or resolved handler?  
  10.         if (handler instanceof String) {  
  11.             String handlerName = (String) handler;  
  12.             handler = getApplicationContext().getBean(handlerName);  
  13.         }  
  14.         return getHandlerExecutionChain(handler, request);  
  15.     }  
AbstractHandlerMapping的getHandlerInternal方法是个抽象方法,由AbstractHandlerMapping的子类AbstractUrlHandlerMapping实现。
  1. protected Object getHandlerInternal(HttpServletRequest request) throws Exception {  
  2.         <span style="color:#ff0000;">String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);  
  3.         Object handler = lookupHandler(lookupPath, request);</span>  
  4.         if (handler == null) {  
  5.             // We need to care for the default handler directly, since we need to  
  6.             // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.  
  7.             Object rawHandler = null;  
  8.             if ("/".equals(lookupPath)) {  
  9.                 rawHandler = getRootHandler();  
  10.             }  
  11.             if (rawHandler == null) {  
  12.                 rawHandler = getDefaultHandler();  
  13.             }  
  14.             if (rawHandler != null) {  
  15.                 // Bean name or resolved handler?  
  16.                 if (rawHandler instanceof String) {  
  17.                     String handlerName = (String) rawHandler;  
  18.                     rawHandler = getApplicationContext().getBean(handlerName);  
  19.                 }  
  20.                 validateHandler(rawHandler, request);  
  21.                 handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);  
  22.             }  
  23.         }  
  24.         if (handler != null && this.mappedInterceptors != null) {  
  25.             Set<HandlerInterceptor> mappedInterceptors =  
  26.                     this.mappedInterceptors.getInterceptors(lookupPath, this.pathMatcher);  
  27.             if (!mappedInterceptors.isEmpty()) {  
  28.                 HandlerExecutionChain chain;  
  29.                 if (handler instanceof HandlerExecutionChain) {  
  30.                     chain = (HandlerExecutionChain) handler;  
  31.                 }  
  32.                 else {  
  33.                     chain = new HandlerExecutionChain(handler);  
  34.                 }  
  35.                 chain.addInterceptors(mappedInterceptors.toArray(new HandlerInterceptor[mappedInterceptors.size()]));  
  36.             }  
  37.         }  
  38.         if (handler != null && logger.isDebugEnabled()) {  
  39.             logger.debug("Mapping [" + lookupPath + "] to " + handler);  
  40.         }  
  41.         else if (handler == null && logger.isTraceEnabled()) {  
  42.             logger.trace("No handler mapping found for [" + lookupPath + "]");  
  43.         }  
  44.         return handler;  
  45.     }  
getLookupPathForRequest方法主要是截取url中对应controller的那一部分,lookupHandler方法根据截取的url字段找到对应的controller,看到红色的部分就和我们注册handlerMapping的那一步相关了,我们早早的就将url的部分字段所对应的controller放到了AbstractUrlHandlerMapping中的handlerMap属性中了,现在就能根据url找到对应的controller了。

  1. protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {  
  2.         // Direct match?  
  3.         <span style="color:#ff0000;">Object handler = this.handlerMap.get(urlPath);</span>  
  4.         if (handler != null) {  
  5.             // Bean name or resolved handler?  
  6.             if (handler instanceof String) {  
  7.                 String handlerName = (String) handler;  
  8.                 handler = getApplicationContext().getBean(handlerName);  
  9.             }  
  10.             validateHandler(handler, request);  
  11.             return buildPathExposingHandler(handler, urlPath, urlPath, null);  
  12.         }  
  13.         // Pattern match?  
  14.         List<String> matchingPatterns = new ArrayList<String>();  
  15.         for (String registeredPattern : this.handlerMap.keySet()) {  
  16.             if (getPathMatcher().match(registeredPattern, urlPath)) {  
  17.                 matchingPatterns.add(registeredPattern);  
  18.             }  
  19.         }  
  20.         String bestPatternMatch = null;  
  21.         Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);  
  22.         if (!matchingPatterns.isEmpty()) {  
  23.             Collections.sort(matchingPatterns, patternComparator);  
  24.             if (logger.isDebugEnabled()) {  
  25.                 logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);  
  26.             }  
  27.             bestPatternMatch = matchingPatterns.get(0);  
  28.         }  
  29.         if (bestPatternMatch != null) {  
  30.             handler = this.handlerMap.get(bestPatternMatch);  
  31.             // Bean name or resolved handler?  
  32.             if (handler instanceof String) {  
  33.                 String handlerName = (String) handler;  
  34.                 handler = getApplicationContext().getBean(handlerName);  
  35.             }  
  36.             validateHandler(handler, request);  
  37.             String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);  
  38.   
  39.             // There might be multiple 'best patterns', let's make sure we have the correct URI template variables  
  40.             // for all of them  
  41.             Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();  
  42.             for (String matchingPattern : matchingPatterns) {  
  43.                 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {  
  44.                     uriTemplateVariables  
  45.                             .putAll(getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath));  
  46.                 }  
  47.             }  
  48.             if (logger.isDebugEnabled()) {  
  49.                 logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);  
  50.             }  
  51.             return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);  
  52.         }  
  53.         // No handler found...  
  54.         return null;  
  55.     }  

废话了那么多,也许大家都已经看的晕头转向了,也没有耐心看下去,那么在这里就对源码中是如何根据url找到对应的controller进行总结一下。

1.SimpleUrlHandlerMapping根据配置文件中的SimpleUrlHandlerMapping的配置,获得一个map集合,map中存储的是{urlString=beanId}。SimpleUrlHandlerMapping调用父类
AbstractUrlHandlerMapping的registerHandler方法。

2.AbstractUrlHandlerMapping的registerHandler方法有SimpleUrlHandlerMapping传入的map中的urlString和beanId,并根据beanId找到对应的bean即controller,将urlString和urlString对应的controller放入AbstractUrlHandlerMapping的handlerMap中。

3.Dispatcher获取IOC容器中已经初始化好的HandlerMapping,再由HandlerMapping调用自己的getHandler方法根据请求返回HandlerExecutionChain对象。AbstractHandlerMapping方法实现了HandlerMapping接口的getHandler方法。AbstractHandlerMapping中的getHandler方法的主要作用是找到controller,并对controller进行封装成HandlerExecutionChain对象,HandlerExecutionChain中除了controller对象外,还有拦截器对象的集合。

4.AbstractHandlerMapping的getHandler方法中又 调用了AbstractHandlerMapping子类的AbstractUrlHandlerMapping getHandlerInternal方法。getHandlerInternal方法就是截取url中对应的controller字段,并以这个字段为key值去AbstractUrlHandlerMapping 的handlerMap中找寻对应的value,即controlle。

总结

handlerMapping的作用

handlerMapping根据用户请求找到执行该请求的controller。

handlerMapping的找到controller过程

1.根据配置文件对url到controller的映射进行注册

2.根据具体的url请求找到执行该请求的controller

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值