SpringMVC源碼解讀,springmvc源碼

來源:互聯網
上載者:User

SpringMVC源碼解讀,springmvc源碼

 

AbstractHandlerMapping實現HandlerMapping介面定的getHandler

  1. 提供getHandlerInternal模板方法給子類實現

  2. 如果沒有擷取Handler,則使用預設的defaultHandler

  3. 如果handler是string類型,從context擷取執行個體

  4. 通過getHandlerExecutionChain封裝handler,添加interceptor

// AbstractHandlerMapping

 1     /** 2      * Look up a handler for the given request, falling back to the default 3      * handler if no specific one is found. 4      * @param request current HTTP request 5      * @return the corresponding handler instance, or the default handler 6      * @see #getHandlerInternal 7      */ 8     public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 9         Object handler = getHandlerInternal(request);10         if (handler == null) {11             handler = getDefaultHandler();12         }13         if (handler == null) {14             return null;15         }16         // Bean name or resolved handler?17         if (handler instanceof String) {18             String handlerName = (String) handler;19             handler = getApplicationContext().getBean(handlerName);20         }21         return getHandlerExecutionChain(handler, request);22     }

// AbstractHandlerMapping

 1     /** 2      * Build a HandlerExecutionChain for the given handler, including applicable interceptors. 3      * <p>The default implementation simply builds a standard HandlerExecutionChain with 4      * the given handler, the handler mapping's common interceptors, and any {@link MappedInterceptor}s 5      * matching to the current request URL. Subclasses may 6      * override this in order to extend/rearrange the list of interceptors. 7      * <p><b>NOTE:</b> The passed-in handler object may be a raw handler or a pre-built 8      * HandlerExecutionChain. This method should handle those two cases explicitly, 9      * either building a new HandlerExecutionChain or extending the existing chain.10      * <p>For simply adding an interceptor, consider calling {@code super.getHandlerExecutionChain}11      * and invoking {@link HandlerExecutionChain#addInterceptor} on the returned chain object.12      * @param handler the resolved handler instance (never {@code null})13      * @param request current HTTP request14      * @return the HandlerExecutionChain (never {@code null})15      * @see #getAdaptedInterceptors()16      */17     protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {18         HandlerExecutionChain chain =19             (handler instanceof HandlerExecutionChain) ?20                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler);21 22         chain.addInterceptors(getAdaptedInterceptors());23 24         String lookupPath = urlPathHelper.getLookupPathForRequest(request);25         for (MappedInterceptor mappedInterceptor : mappedInterceptors) {26             if (mappedInterceptor.matches(lookupPath, pathMatcher)) {27                 chain.addInterceptor(mappedInterceptor.getInterceptor());28             }29         }30 31         return chain;32     }

 

接下來看看AbstractUrlHandlerMapping實現的getHandlerInternal

// AbstractUrlHandlerMapping

 1     /** 2      * Look up a handler for the URL path of the given request. 3      * @param request current HTTP request 4      * @return the handler instance, or {@code null} if none found 5      */ 6     @Override 7     protected Object getHandlerInternal(HttpServletRequest request) throws Exception { 8         // 根據request擷取url 9         String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);10         // 根據url尋找handler11         Object handler = lookupHandler(lookupPath, request);12         if (handler == null) {13             // 如果沒有匹配到handler需要尋找預設的,下面需要將PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE緩衝到request14             // We need to care for the default handler directly, since we need to15             // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.16             Object rawHandler = null;17             if ("/".equals(lookupPath)) {18                 rawHandler = getRootHandler();19             }20             if (rawHandler == null) {21                 rawHandler = getDefaultHandler();22             }23             if (rawHandler != null) {24                 // Bean name or resolved handler?25                 if (rawHandler instanceof String) {26                     String handlerName = (String) rawHandler;27                     rawHandler = getApplicationContext().getBean(handlerName);28                 }29                 // 預留的校正handler模板方法,沒有使用30                 validateHandler(rawHandler, request);31                 // 添加expose屬性到request的攔截器32                 handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);33             }34         }35         if (handler != null && logger.isDebugEnabled()) {36             logger.debug("Mapping [" + lookupPath + "] to " + handler);37         }38         else if (handler == null && logger.isTraceEnabled()) {39             logger.trace("No handler mapping found for [" + lookupPath + "]");40         }41         return handler;42     }

 

// AbstractUrlHandlerMapping

 1     /** 2      * Look up a handler instance for the given URL path. 3      * <p>Supports direct matches, e.g. a registered "/test" matches "/test", 4      * and various Ant-style pattern matches, e.g. a registered "/t*" matches 5      * both "/test" and "/team". For details, see the AntPathMatcher class. 6      * <p>Looks for the most exact pattern, where most exact is defined as 7      * the longest path pattern. 8      * @param urlPath URL the bean is mapped to 9      * @param request current HTTP request (to expose the path within the mapping to)10      * @return the associated handler instance, or {@code null} if not found11      * @see #exposePathWithinMapping12      * @see org.springframework.util.AntPathMatcher13      */14     protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {15         // Direct match? 直接根據url進行尋找handler16         Object handler = this.handlerMap.get(urlPath);17         if (handler != null) {18             // Bean name or resolved handler?19             if (handler instanceof String) {20                 String handlerName = (String) handler;21                 handler = getApplicationContext().getBean(handlerName);22             }23             validateHandler(handler, request);24             return buildPathExposingHandler(handler, urlPath, urlPath, null);25         }26         // Pattern match? 通過運算式進行匹配具體通過AntPathMatcher實現,具體後面分析27         List<String> matchingPatterns = new ArrayList<String>();28         for (String registeredPattern : this.handlerMap.keySet()) {29             if (getPathMatcher().match(registeredPattern, urlPath)) {30                 matchingPatterns.add(registeredPattern);31             }32         }33         String bestPatternMatch = null;34         Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);35         if (!matchingPatterns.isEmpty()) {36             Collections.sort(matchingPatterns, patternComparator);37             if (logger.isDebugEnabled()) {38                 logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);39             }40             // order序號最小的優先順序最高41             bestPatternMatch = matchingPatterns.get(0);42         }43         if (bestPatternMatch != null) {44             handler = this.handlerMap.get(bestPatternMatch);45             // Bean name or resolved handler?46             if (handler instanceof String) {47                 String handlerName = (String) handler;48                 handler = getApplicationContext().getBean(handlerName);49             }50             validateHandler(handler, request);51             String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);52 53             // There might be multiple 'best patterns', let's make sure we have the correct URI template variables54             // for all of them55             Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();56             for (String matchingPattern : matchingPatterns) {57                 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {58                     Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);59                     Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);60                     uriTemplateVariables.putAll(decodedVars);61                 }62             }63             if (logger.isDebugEnabled()) {64                 logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);65             }66             return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);67         }68         // No handler found...69         return null;70     }

 

 

設計用於校正Handler,實際什麼都沒做,包括子類.

 1     /** 2      * Validate the given handler against the current request. 3      * <p>The default implementation is empty. Can be overridden in subclasses, 4      * for example to enforce specific preconditions expressed in URL mappings. 5      * @param handler the handler object to validate 6      * @param request current HTTP request 7      * @throws Exception if validation failed 8      */ 9     protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {10     }

 

封裝handler為HandlerExecutionChain,並添加PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor攔截器.

 1     /** 2      * Build a handler object for the given raw handler, exposing the actual 3      * handler, the {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}, as well as 4      * the {@link #URI_TEMPLATE_VARIABLES_ATTRIBUTE} before executing the handler. 5      * <p>The default implementation builds a {@link HandlerExecutionChain} 6      * with a special interceptor that exposes the path attribute and uri template variables 7      * @param rawHandler the raw handler to expose 8      * @param pathWithinMapping the path to expose before executing the handler 9      * @param uriTemplateVariables the URI template variables, can be {@code null} if no variables found10      * @return the final handler object11      */12     protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,13             String pathWithinMapping, Map<String, String> uriTemplateVariables) {14 15         HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);16         chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));17         if (!CollectionUtils.isEmpty(uriTemplateVariables)) {18             chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));19         }20         return chain;21     }

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.