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 }