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 *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 *NOTE: 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 *
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 *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 *
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 ListmatchingPatterns = new ArrayList ();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 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 uriTemplateVariables = new LinkedHashMap ();56 for (String matchingPattern : matchingPatterns) {57 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {58 Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);59 Map 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 *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 *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, MapuriTemplateVariables) {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 }