?
???? 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