SpringMVC源码解读 - HandlerMapping - AbstractUrlHandlerMapping系列request分发

 

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 request
14      * @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查找handler
11         Object handler = lookupHandler(lookupPath, request);
12         if (handler == null) {
13             // 如果没有匹配到handler需要查找默认的,下面需要将PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE缓存到request
14             // We need to care for the default handler directly, since we need to
15             // 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 found
11      * @see #exposePathWithinMapping
12      * @see org.springframework.util.AntPathMatcher
13      */
14     protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
15         // Direct match? 直接根据url进行查找handler
16         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 variables
54             // for all of them
55             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 found
10      * @return the final handler object
11      */
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     }

 

posted @ 2016-02-22 22:18  出门向左  阅读(2150)  评论(0编辑  收藏  举报