?
???? DispatcherServlet请求处理请求的过程中,会发现getHandler实际上是调用AbstractUrlHandlerMapping.getHandlerInternal()。?通过对该段代码进行走读后发现,是通过handlermap.get(urlPath)获取匹配的handler的,那么该handlerMap是在什么时候进行初始化的呢?
?
/** * Look up a handler for the URL path of the given request. * @param request current HTTP request * @return the handler instance, or <code>null</code> if none found */ @Override protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); Object handler = lookupHandler(lookupPath, request); if (handler == null) { // We need to care for the default handler directly, since we need to // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well. Object rawHandler = null; if ("/".equals(lookupPath)) { rawHandler = getRootHandler(); } if (rawHandler == null) { rawHandler = getDefaultHandler(); } if (rawHandler != null) { // Bean name or resolved handler? if (rawHandler instanceof String) { String handlerName = (String) rawHandler; rawHandler = getApplicationContext().getBean(handlerName); } validateHandler(rawHandler, request); handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); } } if (handler != null && logger.isDebugEnabled()) { logger.debug("Mapping [" + lookupPath + "] to " + handler); } else if (handler == null && logger.isTraceEnabled()) { logger.trace("No handler mapping found for [" + lookupPath + "]"); } return handler; } /** * Look up a handler instance for the given URL path. * <p>Supports direct matches, e.g. a registered "/test" matches "/test", * and various Ant-style pattern matches, e.g. a registered "/t*" matches * both "/test" and "/team". For details, see the AntPathMatcher class. * <p>Looks for the most exact pattern, where most exact is defined as * the longest path pattern. * @param urlPath URL the bean is mapped to * @param request current HTTP request (to expose the path within the mapping to) * @return the associated handler instance, or <code>null</code> if not found * @see #exposePathWithinMapping * @see org.springframework.util.AntPathMatcher */ protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { // Direct match? Object handler = this.handlerMap.get(urlPath); if (handler != null) { // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } validateHandler(handler, request); return buildPathExposingHandler(handler, urlPath, urlPath, null); } // Pattern match? List<String> matchingPatterns = new ArrayList<String>(); for (String registeredPattern : this.handlerMap.keySet()) { if (getPathMatcher().match(registeredPattern, urlPath)) { matchingPatterns.add(registeredPattern); } } String bestPatternMatch = null; Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath); if (!matchingPatterns.isEmpty()) { Collections.sort(matchingPatterns, patternComparator); if (logger.isDebugEnabled()) { logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns); } bestPatternMatch = matchingPatterns.get(0); } if (bestPatternMatch != null) { handler = this.handlerMap.get(bestPatternMatch); // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } validateHandler(handler, request); String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); // There might be multiple ‘best patterns‘, let‘s make sure we have the correct URI template variables // for all of them Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>(); for (String matchingPattern : matchingPatterns) { if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { uriTemplateVariables .putAll(getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath)); } } if (logger.isDebugEnabled()) { logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables); } return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); } // No handler found... return null; }
?
?
?
在服务的启动日志中有这样一段日志:
?
2015-01-01 21:42:38 [ localhost-startStop-1:522842 ] - [ DEBUG ] Returning cached instance of singleton bean ‘org.springframework.web.servlet.handler.MappedInterceptor#0‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524680 ] - [ DEBUG ] Looking for URL mappings in application context: WebApplicationContext for namespace ‘web-servlet‘: startup date [Thu Jan 01 21:34:51 CST 2015]; parent: Root WebApplicationContext 2015-01-01 21:42:40 [ localhost-startStop-1:524698 ] - [ DEBUG ] Returning cached instance of singleton bean ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524699 ] - [ INFO ] Mapped URL path [/bookList.htm] onto handler ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524699 ] - [ DEBUG ] Returning cached instance of singleton bean ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524699 ] - [ INFO ] Mapped URL path [/addNewBook.htm] onto handler ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524700 ] - [ DEBUG ] Returning cached instance of singleton bean ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524700 ] - [ INFO ] Mapped URL path [/book.htm] onto handler ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524701 ] - [ DEBUG ] Returning cached instance of singleton bean ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524701 ] - [ INFO ] Mapped URL path [/deleteBook.htm] onto handler ‘bookController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524709 ] - [ DEBUG ] Returning cached instance of singleton bean ‘downloadController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524710 ] - [ INFO ] Mapped URL path [/download.htm] onto handler ‘downloadController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524720 ] - [ DEBUG ] Returning cached instance of singleton bean ‘reservationController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524721 ] - [ INFO ] Mapped URL path [/reservation.htm] onto handler ‘reservationController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524729 ] - [ DEBUG ] Returning cached instance of singleton bean ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524729 ] - [ INFO ] Mapped URL path [/members] onto handler ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524729 ] - [ DEBUG ] Returning cached instance of singleton bean ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524730 ] - [ INFO ] Mapped URL path [/members.*] onto handler ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524730 ] - [ DEBUG ] Returning cached instance of singleton bean ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524730 ] - [ INFO ] Mapped URL path [/members/] onto handler ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524730 ] - [ DEBUG ] Returning cached instance of singleton bean ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524731 ] - [ INFO ] Mapped URL path [/members/{memberId}] onto handler ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524731 ] - [ DEBUG ] Returning cached instance of singleton bean ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524731 ] - [ INFO ] Mapped URL path [/members/{memberId}.*] onto handler ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524732 ] - [ DEBUG ] Returning cached instance of singleton bean ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524732 ] - [ INFO ] Mapped URL path [/members/{memberId}/] onto handler ‘restMemberController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524745 ] - [ DEBUG ] Returning cached instance of singleton bean ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524746 ] - [ INFO ] Mapped URL path [/exception.htm] onto handler ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524746 ] - [ DEBUG ] Returning cached instance of singleton bean ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524746 ] - [ INFO ] Mapped URL path [/test.json] onto handler ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524747 ] - [ DEBUG ] Returning cached instance of singleton bean ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524747 ] - [ INFO ] Mapped URL path [/exception.json] onto handler ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524748 ] - [ DEBUG ] Returning cached instance of singleton bean ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524749 ] - [ INFO ] Mapped URL path [/test.htm] onto handler ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524749 ] - [ DEBUG ] Returning cached instance of singleton bean ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524749 ] - [ INFO ] Mapped URL path [/handlingTime.htm] onto handler ‘testController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524759 ] - [ DEBUG ] Returning cached instance of singleton bean ‘welcomeController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524760 ] - [ INFO ] Mapped URL path [/locale.htm] onto handler ‘welcomeController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524760 ] - [ DEBUG ] Returning cached instance of singleton bean ‘welcomeController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524761 ] - [ INFO ] Root mapping to handler ‘welcomeController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524761 ] - [ DEBUG ] Returning cached instance of singleton bean ‘welcomeController‘ 2015-01-01 21:42:40 [ localhost-startStop-1:524761 ] - [ INFO ] Mapped URL path [/index.htm] onto handler ‘welcomeController‘
?通过该段日志我们可以找到HandlerMap?的初始化是在初始化应用上下文的时候进行初始化的。具体就是AbstractDetectingUrlHandlerMapping.detectHandlers();
?
?
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping { private boolean detectHandlersInAncestorContexts = false; /** * Set whether to detect handler beans in ancestor ApplicationContexts. * <p>Default is "false": Only handler beans in the current ApplicationContext * will be detected, i.e. only in the context that this HandlerMapping itself * is defined in (typically the current DispatcherServlet‘s context). * <p>Switch this flag on to detect handler beans in ancestor contexts * (typically the Spring root WebApplicationContext) as well. */ public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) { this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts; } /** * Calls the {@link #detectHandlers()} method in addition to the * superclass‘s initialization. */ @Override public void initApplicationContext() throws ApplicationContextException { super.initApplicationContext(); detectHandlers(); }
?
/** * Register all handlers found in the current ApplicationContext. * <p>The actual URL determination for a handler is up to the concrete * {@link #determineUrlsForHandler(String)} implementation. A bean for * which no such URLs could be determined is simply not considered a handler. * @throws org.springframework.beans.BeansException if the handler couldn‘t be registered * @see #determineUrlsForHandler(String) */ protected void detectHandlers() throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Looking for URL mappings in application context: " + getApplicationContext()); } String[] beanNames = (this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); // Take any bean name that we can determine URLs for. for (String beanName : beanNames) { String[] urls = determineUrlsForHandler(beanName); if (!ObjectUtils.isEmpty(urls)) { // URL paths found: Let‘s consider it a handler. registerHandler(urls, beanName); } else { if (logger.isDebugEnabled()) { logger.debug("Rejected bean name ‘" + beanName + "‘: no URL paths identified"); } } } }
?
?
原文:http://zhangwei-david.iteye.com/blog/2171726