Controller search of spring MVC learning notes (based on spring 4.0.3)
0 summary
This article briefly explains the processor mapping of spring MVC from the source code level, that is, the detailed process of finding controller
1. Spring MVC request process
The controller finds the corresponding steps 1 to 2 in the above figure
2 spring MVC initialization process
2.1 know two classes first
1.RequestMappingInfo
Encapsulating requestmapping annotations
Contains information about the HTTP request header
An instance corresponds to a requestmapping annotation
2.HandlerMethod
Encapsulating the request processing method of the controller
It includes the bean object to which the method belongs, the method object corresponding to the method, the parameters of the method, etc
Inheritance relationship of requestmappinghandlermapping
When spring MVC is initialized
First, execute the afterpropertieset of requestmappinghandlermapping
Then enter the afterpropertieset of abstracthandlermethodmapping
This method will enter the inithandlermethods of the class
Responsible for scanning beans from ApplicationContext, and then finding and registering processor methods from beans
RequestMappingHandlerMapping#isHandler
The above method determines whether the current bean definition has a controller annotation or a requestmapping annotation
If only requestmapping takes effect? unable!
In this case, this class will not be registered as a spring bean during spring initialization, and this class will not be traversed when traversing beannames. Therefore, it is OK to replace the controller with component, but generally not
When the bean is determined to be a handler, the specific handler method (that is, the specifically defined request processing method under the controller class) will be found from the bean. The search code is as follows
The above code calls getmappingformethod in two places
Use the method and type level requestmapping annotation to create requestmappinginfo
The function of this method is to create a requestmappinginfo object according to the handler method method. First, judge whether the mehtod contains the requestmpping annotation. If so, create a requestmappinginfo object directly according to the content of the annotation. After creation, judge whether the bean to which the current method belongs also contains the requestmapping annotation. If the annotation is included, a requestmappinginfo object will be created according to the annotation on the class. Then, the requestmappinginfo object on the merge method is, and finally the merged object is returned. Looking back at the detecthandlermethods method, I think getmappingformethod is called in two places. I think it can be optimized. When I judge whether the method is a handler in the first place, the created requestmappinginfo object can be saved and used directly in the future, which eliminates the process of creating requestmappinginfo object. Then enter the registerhandlermehtod method, as follows
The type of t here is requestmappinginfo. This object is the related information of the requestmapping annotation of the method under the encapsulated specific controller. A requestmapping annotation corresponds to a requestmappinginfo object. Similar to requestmappinginfo, handlermethod encapsulates the specific processing methods under controlelr. First look at the first line of the method, and create the handlermethod object according to the handler and mehtmethod. The second line uses the handlermethods map to obtain the handlermethod corresponding to the current mapping. Then determine whether the same requestmapping configuration exists. The following configuration will cause the invocation of init method failed to be thrown here; nested exception is java. lang.IllegalStateException: Ambiguous mapping found. Cannot map... abnormal
Check whether the requestmapping configuration is ambiguous in the springmvc startup (initialization) phase, which is one of the ways to check ambiguity (a place to check ambiguity at run time will be mentioned later). After confirming that the configuration is normal, the requestmappinginfo and handlermethod objects will be added to the handlermethods (LinkedHashMap), and then the value of the requestmapping annotation and the reuqestmappinginfo object will be added to the urlmap.
Simple summary of registerhandlermethod method
There are three main responsibilities of this method
1. Check whether the requestmapping annotation configuration is ambiguous.
2. Build a mapping map from requestmappinginfo to handlermethod. This map is the member variable handlermethods of abstracthandlermethodmapping. LinkedHashMap。
3. Construct the member variables urlmap and multivaluemap of abstracthandlermethodmapping. This data structure can be understood as map >. The string type key stores the value of the requestmapping annotation on the processing method. Is the specific URI
First, there are the following controllers
After initialization, the structure of urlmap corresponding to abstracthandlermethodmapping is as follows
The above is the main process of spring MVC initialization
Search process
In order to understand the search process, take a question and look at the existing controllers as follows
Have the following requests
Which method does the request enter?
After receiving the request, the web container (tomcat, jetty) sends it to the dispatcher servlet for processing. FrameworkServlet calls the corresponding request method (eg:get calls doGet), then calls the processRequest method. After entering the processrequest method, after a series of processing, enter the doservice method at line: 936. Then enter the dodispatch method at line856. Get the processor handler of the current request at line: 896. Then enter the lookuphandlermethod method of abstracthandlermethodmapping. The code is as follows
Enter the lookuphandlermethod method, where lookuppath = "/ lookuptest / test1", according to the lookuppath, that is, the URI of the request. Directly find the urlmap and obtain the directly matched requestmappinginfo list. Three requestmappinginfo will be matched here. as follows
Then enter the addmatchingmappings method
The responsibility of this method is to traverse whether the URI of the current request matches the requestmappinginfo in the mappings. If so, create the same requestmappinginfo object. Then get the handlermethod corresponding to requestmappinginfo. Then create a match object and add it to the matches list. After executing the addmatchingmappings method, return to lookuphandlermethod. At this time, matches also has three requestmappinginfo objects that can match. The next step is to sort the matchers list, and then get the first element of the list as the best match. Returns the handlermethod of match. Here, go to the CompareTo method of requestmappinginfo and take a look at the specific sorting logic. The code is as follows
It can be seen from the code that the matching order is value > parameters > headers > consumers > Products > methods > custom. You can easily get the answer to the previous questions. When the value is the same, params can match first. So that request goes into the test3 () method. Go back to lookuphandlermethod and find handlermethod in. Spring MVC will also check the configuration ambiguity again here. The principle of checking here is to compare the two requestmappinginfo with the highest matching degree. There may be a question here about the ambiguity of checking the configuration when initializing spring MVC. Why is it checked again here. If there are two methods in the controller, the following configuration can pass the initialization ambiguity check.
Execute now http://localhost:8080/SpringMVC -The demo / lookuptest / test5 request will throw Java in the lookuphandlermethod method lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path ' http://localhost:8080/SpringMVC -Demo / lookuptest / test5 'exception. This exception is thrown here because the CompareTo method of requestmethodsrequestcondition is the number of methods to compare. The code is as follows
When do I match wildcards? When the requestmappinginfo that directly matches the value cannot be obtained through urlmap, the wildcard matching will be used to enter the addmatchingmappings method.
summary
The above is the whole content of this article. I hope the content of this article has a certain reference value for your study or work. If you have any questions, you can leave a message. Thank you for your support for programming tips.