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
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 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.
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 is a very important class. In addition to inheriting from
AbstractHandlerMapping abstract class,
AbstractHandlerMethodMapping also implements the
In Spring if a class implements the
InitializingBean interface, the Spring container will call the afterPropertiesSet method of the bean when it is instantiated.
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.
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 p
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
- The corresponding mapping between request request and handler is established by the detectHandlerMethods method.
detectHandlerMethods method does two main things.
getMappingForMethodmethod to find the method with the
@RequestMappingannotation through the handler. In
getMappingForMethodmethod in just an abstract method, the specific implementation is in the subclass
RequestMappingHandlerMappingclass, to achieve the specific business logic.
registerHandlerMethodmethod to register the found method. The so-called registration is actually the found
HandlerMothedinto a Map. If the same
HandlerMothedis registered for a second time, an exception will be thrown.
AbstractHandlerMethodMapping class, the template method
getHandlerInternal of the parent class
AbstractHandlerMapping is overridden.
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 corresponding
HandlerMethodby using the two parameters request and lookupPath.
- In the case of finding a
createWithResolvedBeanmethod of the
HandlerMethodwill be called. This method determines whether this
HandlerMethodobject. 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 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
SpringMVC will get the corresponding Handler based on this
Spring MVC container in the initialization of the
HandlerMapping type components, the final initialization of the
AbstractHandlerMethodMapping series of components, is
RequestMappingHandlerMapping mainly overrides the three methods of the parent class.
initializationmethod of the parent class is overridden and an object of type
BuilderConfigurationis created in the
afterPropertiesSetmethod. Then for the
BuilderConfigurationobject, the properties are set.
The main purpose is to determine what type of Handler to get, and to play a filtering role on the Handler, only take the
@RequestMappingtwo annotated types of Handler.
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 implements the
RequestCondition interface. The interface
RequestCondition is Spring MVC’s conceptual modeling of a request matching condition.
AbstractUrlHandlerMapping series can be seen from the name, it mainly deals with the relationship between url and handler.
AbstractUrlHandlerMapping class firstly puts the mapping relationship between url and handler into a Map, and then gets the corresponding handler by url.
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.
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
setDefaultHandlermethod 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.
AbstractUrlHandlerMapping class specifies how to get the corresponding handler from a url.
AbstractUrlHandlerMapping class overrides the getHandlerInternal method. The logic to get the handler from the url is written 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 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.
buildPathExposingHandler method is used to add some interceptors to this Handler.
buildPathExposingHandler method mainly registers two internal interceptors to the Handler. They are the
PathExposingHandlerInterceptor and the
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.
determineUrlsForHandler(beanName) method in the
AbstractDetectingUrlHandlerMapping class is just an abstract method, which is left to the subclasses for concrete implementation.
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
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 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
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.