Notice
I wrote this article and was originally published on Qiita on 1 July 2021.
What is org.springframework.web.servlet.HandlerMapping interface?
From the document from Spring Framework, it says "Interface to be implemented by objects that define a mapping between requests and handler objects.". In my notice board example application, following bean is created when started.
| Order | Bean Name | Class | Where it created | 
|---|---|---|---|
| 2147483647 | welcomePageHandlerMapping | org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping | org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.EnableWebMvcConfiguration.welcomePageHandlerMapping(ApplicationContext, FormattingConversionService, ResourceUrlProvider) | 
| 2147483646 | resourceHandlerMapping | org.springframework.web.servlet.handler.SimpleUrlHandlerMapping | org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping() | 
| 2 | beanNameHandlerMapping | org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping | org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.beanNameHandlerMapping() | 
| 0 | requestMappingHandlerMapping | org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping | org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.EnableWebMvcConfiguration.requestMappingHandlerMapping() | 
| -2147483647 | faviconHandlerMapping | org.springframework.web.servlet.handler.SimpleUrlHandlerMapping | org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter.FaviconConfiguration.faviconHandlerMapping() | 
requestMappingHandlerMapping handles bean class which have org.springframework.web.bind.annotation.RequestMapping annotation.
How I know this? Please refer to here.
When it been loaded
First, beans are created by ApplicationContext instance.
Then when org.springframework.web.servlet.DispatcherServlet instance is created and during initialization, org.springframework.web.servlet.DispatcherServlet.initHandlerMappings(ApplicationContext) is called and all bean with org.springframework.web.servlet.HandlerMapping interface will been lookup. Its reference will be saved into DispatcherServlet's internal structure. Following is related code.
/**
 * Initialize the HandlerMappings used by this class.
 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
 * we default to BeanNameUrlHandlerMapping.
 */
private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;
    if (this.detectAllHandlerMappings) {
        // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
        Map<String, HandlerMapping> matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            // We keep HandlerMappings in sorted order.
            AnnotationAwareOrderComparator.sort(this.handlerMappings);
        }
    }
    else {
        ...
    }
    ...
}
Look up which bean handles particular URI
In method org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) you can see how Spring MVC actually handle a request. The code which lookup URI bean mapping is
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
    noHandlerFound(processedRequest, response);
    return;
}
And in method org.springframework.web.servlet.DispatcherServlet.getHandler(HttpServletRequest), request will be passed into list of instances with org.springframework.web.servlet.HandlerMapping interface which is built before. If mapping is found in one instance, lookup will be stopped and org.springframework.web.servlet.HandlerExecutionChain will be returned. Following is the code.
/**
 * Return the HandlerExecutionChain for this request.
 * <p>Tries all handler mappings in order.
 * @param request current HTTP request
 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
 */
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        for (HandlerMapping mapping : this.handlerMappings) {
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}
    
Top comments (0)