preface

For a Web application, we make a request from the browser, the request goes through a series of distribution and processing, and finally into the method we specify. What is the flow of this series?

Spring MVC request flow

I remember that when I was just entering the workplace, I often memorized the Spring MVC process before the interview. What impressed me most was that a request would be first distributed through DispatcherServlet, which is the entrance class of Spring MVC. Here is an overview of the flow of a request (see picture from Spring In Action) :

  1. A request comes in and it arrivesDispatcherServlet, butDispatcherServletIt’s not clear where the request is going.
  2. DispatcherServletAfter receiving the request, it queries the HandlerMapping and sends it according to the browserURLResolve which controller the request should ultimately call.
  3. After reaching the corresponding Controller, some logic processing is done, and some return information is generated after the processing is done, i.eModel, and then you need to select the corresponding view name.
  4. The model (Model) and views (View) to the corresponding View Resolver, which combines the model with the View.
  5. The model and view are combined to produce a complete view, which is eventually returned to the front end.

This is a traditional complete Spring MVC flow. Why is this a traditional flow? Because this process is used when there is no separation of the front and back ends, the background directly returns the page to the browser for rendering, but now most applications are separated from the front and back ends, the background directly generates a Json string and returns it directly to the front end, without the view parser processing, that is to say, after the separation of the front and back ends, The process is simplified to 1-2-3-4-7 (where the fourth step typically returns Json data).

Spring MVC has two phases

Spring MVC can be divided into two main processes: initialization and request processing. The initialization process is mainly to map and store the defined RequestMapping mapping path and methods in the Controller one by one, so that after receiving the request, the request can be processed and the corresponding method can be invoked to respond to the request.

Initialize the

The entry method to the initialization process is the Init () method of DispatchServlet, which is not actually in DispatchServlet, so we continue to look for the parent class, You will find that the init method is in the parent class HttpServletBean of its parent class (FrameworkServlet).

HttpServletBean#init()

In this method, some servlet-specific configuration (web.xml) is first done, and the initServletBean() method is called, which is an empty template method with business logic implemented by subclass FrameworkServlet.

FrameworkServlet#initServletBean

This method has no business logic of its own. It initializes the WebApplicationContext object. WebApplicationContext inherits from ApplicationContext and is used to handle the context of the Web application.

FrameworkServlet#initWebApplicationContext

InitWebApplicationContext () method is mainly to find a context, can not find will create a context, created, will eventually call methods configureAndRefreshWebApplicationContext (cwac) method, This method eventually calls the refresh() method, which initializes the IOC container, after setting some basic container identifiers.

When the refresh() method is called to initialize the IOC container, the onRefresh() method is eventually called, which is also a template hook method implemented by subclasses, returning to our Spring MVC entry class DispatcherServlet.

DispatchServlet#onRefresh

The onRefresh() method is the final step in Spring MVC initialization, which initializes nine components that might be needed in the Spring MVC process.

Spring MVC consists of nine components

MultipartResolver

Familiar with the components, is mainly used to handle file upload Request, through the common Request object packaged into MultipartHttpServletRequest for processing.

LocaleResolver

LocaleResolver is used to initialize the locale. LocaleResolver resolves the locale from the Request object, such as zh-CN, for example. The locale is used for template parsing and internationalization.

ThemeResolver

In Spring MVC, a set of themes corresponds to a.properties file, which can store all resources related to the current theme, such as images, CSS styles, etc.

HandlerMapping

It is used to find the Handler, such as the method in the Controller. The main purpose of this method is to store the mapping between url and calling method. After storing the mapping relationship, the subsequent request comes in, we can know which method in which Controller is called. And what the parameters of the method are.

HandlerAdapter

This is an adapter because there are many different types of handlers supported in Spring MVC, but ultimately the request to the Servlet can only be in the form of doService(REQ, RESP), so the HandlerAdapter is used to accommodate the transformation format.

HandlerExceptionResolver

This component is mainly used to handle exceptions, but the name is obvious, this will only handle the exception generated when handling Handler, and then set the corresponding ModelAndView according to the exception, and then Render the page to Render.

RequestToViewNameTranslator

This primary key basically gets the view name from the Request.

ViewResolver

This component will be dependent on RequestToViewNameTranslator component to get to the name of the View, because the View name is string format, so there will be the View name string format conversion become the View type View, finally through a series of analytical and variable substitution operation returns to the front end of a page.

FlashMapManager

This primary key is mainly used to manage the FlashMap, so what is the use of the FlashMap? In order to understand this, we have to mention redirection, sometimes we submit a request to need redirection, so what if there are too many parameters or we don’t want to concatenate parameters to the URL (sensitive data, etc.)? Because parameters are not concatenated on the URL redirection cannot carry parameters.

FlashMap is designed to solve this problem. We can write parameters to the OUTPUT_FLASH_MAP_ATTRIBUTE of the request before the request is redirected, so that in the handler after the redirection, Spring will automatically set it to the Model so that we can fetch the parameters we passed from the Model.

Handle the request

After the nine components are initialized, the Spring MVC initialization is complete and it is time to receive and process the request. Where is the entry point for processing the request? The entry method to handle the request is the doService method in the DispatcherServlet, which in turn calls the doDispatch method.

DispatcherServlet#doDispatch

The key of this method is to call the getHandler method, which will get the HandlerMapping of the previous nine components, and then reflect and call the corresponding method to complete the request. After completing the request, some operations like view transformation will follow. Finally return ModelAndView, but now the front and back ends are separated, basically do not need to use the view model, here we do not analyze the subsequent process, mainly analyze HandlerMapping initialization and query process.

DispatcherServlet#getHandler

/ / handllerMappings (); / / GetMappings (); / / GetMappings (); / / GetMappings (); / / GetMappings (); / / GetMappings (); The most commonly used two implementations for the RequestMappingHandlerMapping and BeanNameUrlHandlerMapping.

AbstractHandlerMapping#getHandler

AbstractHandlerMapping is an abstract class whose getHandlerInternal method is also a template method: AbstractHandlerMapping

It invokes the subclasses implement getHandlerInternal method, in the end, and the subclass implementation may have more than one here, one of the most important is AbstractHandlerMethodMapping and AbstractUrlHandlerMapping two abstract class, So which implementation class will be called?

If sure we can have a look at the class diagram, as we mentioned above, there are two very main HandlerMapper implementation classes: RequestMappingHandlerMapping and BeanNameUrlHandlerMapping. So let’s look at the class diagram relationship of these two classes respectively:

As you can see, the abstract superclasses of these two implementation classes correspond to two subclasses of AbstractHandlerMapping, so it depends on what type we want to see.

  • RequestMappingHandlerMapping: mainly used to store RequestMapping annotate relevant controller and url mapping relationship.

  • BeanNameUrlHandlerMapping: mainly used for processing the Bean name directly with/at the beginning of the controller and the url mapping relationship.

In addition to these two types of HandlerMapping, there are other HandlerMapping in Spring, such as SimpleUrlHandlerMapping, etc.

Mentioned this several HandlerMapping, the most commonly used for us, the most familiar it is RequestMappingHandlerMapping, here we are with this as an example for analysis, so we should be

AbstractHandlerMethodMapping#getHandlerInternal

The lookupHandlerMethod method has no logic of its own. The main core of this method is to find the Handler logic in the lookupHandlerMethod method. And now it’s going to be a HandlerMethod type, and that’s because there are different types of handlers, and so far we’re pretty much under the concrete type, so the type is going to be the concrete type, and if we look at another branch line, we’re going to return something else, It is because there are many different types of HandlerMapping objects that you need to obtain the Hanlder for unified execution. In the DispatcherServlet, the getHandlerAdapter method is again called to further encapsulate the HandlerAdapter object before the method is called

AbstractHandlerMethodMapping#lookupHandlerMethod

This method mainly obtains the hit method from mappingRegistry, and then goes through a series of judgment comparisons, because some urls may correspond to multiple methods with different request types, such as a GET method, a POST method, or some other attributes are different, etc. This logic is further implemented in the addMatchingMappings method, which adds the matched result to the matches collection.

There is one object in this method that is critical, and that is the mappingRegistry, because eventually we get the corresponding HandlerMtthod from the URL:

If you look at this object, it’s pretty obvious that this object just maintains some Map objects, so it’s easy to guess that somewhere, there must be a mapping between url and HandlerMapping or HandlerMethod. GetMappingsByUrl = getMappingsByUrl = getMappingsByUrl = getMappingsByUrl = getMappingsByUrl Can easily find the mapping relationship of the Map object is AbstractHandlerMethodMapping afterPropertiesSet method (AbstractHandlerMethodMapping has been realized InitializingBean interface), that is, after the object is initialized, our URL and Handler mappings are stored in a collection Map in the MappingRegistry object.

AbstractHandlerMethodMapping initialization

There is no logic in the afterPropertiesSet method and initHandlerMethods are called directly.

AbstractHandlerMethodMapping#initHandlerMethods

In the initHandlerMethods method, all beans are first fetched from the Spring context, The HandlerMethod is then further parsed from the Bean with the RequestMapping annotation and the Controller annotation to get it.

AbstractHandlerMethodMapping#detectHandlerMethods

In this method, we get all the methods in the Controller by reflection, and then call the registerHandlerMethod method to register the relevant information into the various Map collections in the MappingRegistry object:

AbstractHandlerMethodMapping#register

RegisterHandlerMethod method can directly call AbstractHandlerMethodMapping regidter methods of object holds mappingRegistry object, The meta information on the Controller methods, such as parameters, paths, request methods, etc., is parsed and registered into the corresponding Map collection to complete the initialization.

conclusion

Key RequestMappingHandlerMapping as example, this paper analysed how to initialize HandlerMethod in the Spring, and finally at the time of call and how to url access to the corresponding method and finally complete the whole process.