HandlerMapping Overview
The HandlerMapping component parses a Request and finds a Handler that handles the Request, which is generally understood as a method in the Controller.
The HandlerMapping component does two main events.
- when the component is initialized, it registers the Request request and the corresponding Handler, which actually means that the Request and the corresponding Handler exist in a map as a key-value pair.
- parse each Request request and find the corresponding handler in the registered map.
In the SpringMvc source code, HandlerMapping is defined as an interface. In addition to defining several property fields, the interface defines only one getHandler method.
HandlerMapping class system

As you can see from the above class diagram, the HandlerMapping component is divided into two families. One family inherits from AbstractHandlerMethodMapping, and the other family inherits from AbstractUrlHandlerMapping. Both abstract classes inherit from AbstractHandlerMapping.
AbstractHandlerMapping
AbstractHandlerMapping is an abstract class that implements the HandlerMapping interface, and it is a very basic class from which all subclasses of HandlerMapping are inherited. AbstractHandlerMapping uses the template pattern for the overall design, and each subclass overrides the template methods to achieve the appropriate functionality.
Since AbstractHandlerMappin abstract class inherits the HandlerMapping interface, it must implement the getHandler method. In the AbstractHandlerMappin class, the specific code is as follows.
|
|
Special attention should be paid to the getHandlerInternal(request) method in the getHandler method, which is a boilerplate method. In the AbstractHandlerMapping class, the getHandlerInternal(request) method is just an abstract method that doesn’t do anything. This method is specifically reserved for subclasses of AbstractHandlerMapping to override and thus implement their own business logic.
AbstractHandlerMapping also inherits from the WebApplicationObjectSupport class and overrides the initApplicationContext method of that parent class.
|
|
In the initApplicationContext method, three methods are defined.
-
extendInterceptors(**this**.interceptors)extendInterceptors is a template method that gives subclasses an entry point to modify this.interceptors interceptors. -
detectMappedInterceptors(**this**.addedInterceptors)detectMappedInterceptors method is to add all beans of type MappedInterceptor in Spring MVC to the collection of this.addedInterceptors. -
initInterceptors()initInterceptors is to initialize the interceptors, add all the interceptors wrapped in the this.interceptors collection to the this.adoptedInterceptors collection.
AbstractHandlerMethodMapping series
AbstractHandlerMethodMapping
AbstractHandlerMethodMapping is a very important class. In addition to inheriting from AbstractHandlerMapping abstract class, AbstractHandlerMethodMapping also implements the InitializingBean interface.
Handler registration
In Spring if a class implements the InitializingBean interface, the Spring container will call the afterPropertiesSet method of the bean when it is instantiated.
The AbstractHandlerMethodMapping class does the initialization and registration work when it overrides the afterPropertiesSet method of the InitializingBean interface. This is the first step of the HandlerMapping component, registering the Request request and the corresponding Handler first.
The afterPropertiesSet method of the AbstractHandlerMethodMapping class is shown in the following code.
You can see that the initHandlerMethods() method is called in the afterPropertiesSet method of the AbstractHandlerMethodMapping class. Looking at the name of the initHandlerMethods() method, you can see that it actually does the initialization work.
|
|
In the initHandlerMethods() method, the getCandidateBeanNames method first gets the names of all the beans in the Spring container. The bean name is passed through the loop to the processCandidateBean(beanName) method.
The processCandidateBean(beanName) method does three main things.
- Find the type corresponding to the bean by its name.
- Filter out beans that do not match the criteria by the isHandler method. isHandler method is a template method and the specific logic is implemented in the subclass
RequestMappingHandlerMapping. isHandler method will only select beans that contain@Controllerand@RequestMappingannotations. - The corresponding mapping between request request and handler is established by the detectHandlerMethods method.
The detectHandlerMethods method does two main things.
-
use the
getMappingForMethodmethod to find the method with the@RequestMappingannotation through the handler. InAbstractHandlerMethodMappingclass,getMappingForMethodmethod in just an abstract method, the specific implementation is in the subclassRequestMappingHandlerMappingclass, to achieve the specific business logic. -
use the
registerHandlerMethodmethod to register the found method. The so-called registration is actually the foundHandlerMothedinto a Map. If the sameHandlerMothedis registered for a second time, an exception will be thrown.
Handler lookup
In the AbstractHandlerMethodMapping class, the template method getHandlerInternal of the parent class AbstractHandlerMapping is overridden.
|
|
In the getHandlerInternal method, there are three main events that are done.
- In the
initLookupPathmethod, a request is converted into a url. - Then use the
lookupHandlerMethodmethod to find the correspondingHandlerMethodby using the two parameters request and lookupPath. - In the case of finding a
HandlerMethodobject, thecreateWithResolvedBeanmethod of theHandlerMethodwill be called. This method determines whether thisHandlerMethodobject. If it is of type String, it is just a String. If it is of type String then it is just the name of a bean and the bean will be found in the Spring container based on the name of the bean.
RequestMappingInfoHandlerMapping
The RequestMappingInfoHandlerMapping class mainly overrides the getMatchingMapping method of the parent class. getMatchingMapping method returns a RequestMappingInfo object that matches various RequestCondition based on the current request. RequestMappingInfo object that matches various RequestCondition.
SpringMVC will get the corresponding Handler based on this RequestMappingInfo object.
RequestMappingHandlerMapping
Spring MVC container in the initialization of the HandlerMapping type components, the final initialization of the AbstractHandlerMethodMapping series of components, is RequestMappingHandlerMapping.
RequestMappingHandlerMapping mainly overrides the three methods of the parent class.
-
afterPropertiesSetThe
initializationmethod of the parent class is overridden and an object of typeBuilderConfigurationis created in theafterPropertiesSetmethod. Then for theBuilderConfigurationobject, the properties are set. -
isHandlerThe main purpose is to determine what type of Handler to get, and to play a filtering role on the Handler, only take the
@Controllerand@RequestMappingtwo annotated types of Handler. -
getMappingForMethod
The getMappingForMethod method is mainly used to create the corresponding RequestMappingInfo object by method. The program first gets the RequestMapping annotation from the method object. From the RequestMapping annotation information, it creates “PathMapping”, “HeaderMapping”, “RequestParameterMapping”, “MIMEMapping”, “MIMEMapping”, “MIMEMapping”, and “MIMEMapping”. “MIME matchable”, “MIME matchable”, “request method matchable”, and other RequestCondition interface instances. Finally these RequestCondition interface instances are combined to create a RequestMappingInfo object and SpringMVC registers the request and Handler mapping relationship based on the RequestMappingInfo object.
The RequestMappingInfo object implements the RequestCondition interface. The interface RequestCondition is Spring MVC’s conceptual modeling of a request matching condition.
AbstractUrlHandlerMapping series
AbstractUrlHandlerMapping series can be seen from the name, it mainly deals with the relationship between url and handler.
The AbstractUrlHandlerMapping class firstly puts the mapping relationship between url and handler into a Map, and then gets the corresponding handler by url.
AbstractUrlHandlerMapping
AbstractUrlHandlerMapping class, like AbstractHandlerMethodMapping class, also inherits AbstractHandlerMapping abstract class. All url and HandlerMapping related subclasses are inherited from the AbstractUrlHandlerMapping parent class.
AbstractUrlHandlerMapping also implements the MatchableHandlerMapping interface, which defines a match method for matching.
HandlerMap registration
In AbstractUrlHandlerMapping class, the method registerHandler is specifically responsible for registering the handler.
Handler registration is actually storing the url and the corresponding handler in the hash map called handlerMap.
|
|
In the registerHandler method, there are 4 main things done.
- if the handler is not lazy loaded and the handler is of string type. At this point the handler as a BeanName, in the Spring container to get the bean object of the handler.
- the urlPath is verified, if a urlPath corresponds to more than one different handler, the code will throw an exception.
- the special urlPath is handled separately, the
setRootHandlermethod andsetDefaultHandlermethod are called for “/”, “/*” respectively for special handling. - record the correspondence between url and handler in handlerMap. The code
this.handlerMap.put(urlPath, resolvedHandler)stores the url and handler into the hash hash by key-value pairs.
Handler lookup
The AbstractUrlHandlerMapping class specifies how to get the corresponding handler from a url.
The AbstractUrlHandlerMapping class overrides the getHandlerInternal method. The logic to get the handler from the url is written in the getHandlerInternal method.
|
|
In the getHandlerInternal method, the program will first get a url based on the request, and then use the lookupHandler method to get the corresponding Handler.
lookupHandler method
The lookupHandler method is a method to find the corresponding Handler by url. lookupHandler is firstly retrieved directly from the HandlerMap. If the Handler is found, it will be returned directly.
If you can’t get it directly from the handlerMap, you will use the PathPattern to match the pattern. If a url matches more than one PathPattern, the PathPattern will be sorted and the best one will be taken.
If the Handler is of type String, then the Handler is the name of the Handle bean. Then find the corresponding bean in the Spring container based on this BeanName.
After getting the Handler, the Handler is validated using validateHandler. validateHandler is a template method, which is mainly left to subclasses to extend the implementation.
Finally, the buildPathExposingHandler method is used to add some interceptors to this Handler.
buildPathExposingHandler
The buildPathExposingHandler method mainly registers two internal interceptors to the Handler. They are the PathExposingHandlerInterceptor and the UriTemplateVariablesHandlerInterceptor interceptor.
AbstractDetectingUrlHandlerMapping
In AbstractDetectingUrlHandlerMapping class, the main thing is to override the initApplicationContext() method of the parent class. In the initApplicationContext() method, the detectHandlers() method is called.
|
|
In the method detectHandlers() is called, the following steps are done.
- Get the names of all beans in the Spring container.
- loop through all the bean names and call the determineUrlsForHandler method for each beanName to get the url corresponding to that beanName.
- then call the registerHandler(urls, beanName) method of the parent class to register the url and the handler.
The determineUrlsForHandler(beanName) method in the AbstractDetectingUrlHandlerMapping class is just an abstract method, which is left to the subclasses for concrete implementation.
BeanNameUrlHandlerMapping
The Spring MVC container initializes the BeanNameUrlHandlerMapping component when it initializes the components of the HandlerMapping type by default when it initializes the components of the AbstractUrlHandlerMapping series.
The BeanNameUrlHandlerMapping class inherits from the parent class AbstractDetectingUrlHandlerMapping, and the child class mainly overrides the determineUrlsForHandler method. determineUrlsForHandler method Finally, the name of the bean and the corresponding bean object will be registered to the handlerMap HashMap object.
SimpleUrlHandlerMapping
SimpleUrlHandlerMapping class inherits from the parent class AbstractUrlHandlerMapping, which has a Map<String, Object> type urlMap property. SimpleUrlHandlerMapping class will iterate through the urlMap in the registerHandlers(Map<String, Object> urlMap) method and then call AbstractUrlHandlerMapping parent class registerHandler(String urlPath, Object handler) method to register the url and HandlerMapping.
In addition to the urlMap property of type Map<String, Object>. the SimpleUrlHandlerMapping class also provides the use of Properties for url registration. With the setMappings(Properties mappings) method, SimpleUrlHandlerMapping will merge the mappings into the urlMap property. Then the registration logic of urlMap properties is carried out.