“This is the 15th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

Based on the latest Spring 5.x, the core components of Spring MVC are introduced in detail, including Handler, HandlerMapping, HandlerAdapter, HandlerExceptionResolver, ViewResolver and other components. Finally, I outlined the Spring MVC request execution process and the default Spring MVC component.

Now that we’ve looked at the basic concepts of Spring MVC and the parent-child container concept, Spring MVC is a component architecture, let’s look at the core components of Spring MVC, the request execution process, and the default Spring MVC component.

Spring MVC learning series

Spring MVC Learning (1) — An introduction to MVC and an introduction to Spring MVC

Spring MVC Learning (2) – The container hierarchy in Spring MVC and the concept of parent-child containers

Spring MVC Learning (3) – The core components in Spring MVC and the execution flow of the request

Spring MVC Learning (4) — A detailed introduction and use case of the ViewSolvsolver view parser

Spring MVC Learning (5) – Annotation-based Controller configuration complete solution

Spring MVC Learning (6) – Spring data type conversion mechanism

Annotation-based declarative Validation of data

Spring MVC Learning (8) – HandlerInterceptor processor interceptor mechanism complete solution

Spring MVC Learning (9) – Project unified exception handling mechanism details and use cases

Spring MVC Learning (10) – File upload configuration, path configuration of DispatcherServlet, request and response content encoding

Spring MVC Learning (11) – Introduction to cross-domain and solving cross-domain problems using CORS

@[toc]

1 Core components of Spring MVC

Spring MVC is a component-based Web framework in which each function point is handled by a different component. One of the advantages of this approach is that each component has a clear division of work and works with each other to handle and respond to requests. And each component is a separate extension point that can be easily extended without particularly caring about other components, which is quite flexible (it’s important to understand the relationships between components before you customize them).

Like many other Web frameworks, Spring MVC is designed around the dispatch Controller pattern, where DispatcherServlets provide the overall logic for request processing and distribution, with configurable components doing the actual work. The model is flexible and supports multiple workflows. The DispatcherServlet is also called a front-end controller.

As with any Servlet, you need to use JavConfig according to the Servlet specification or declare and map dispatcherServlets in web.xml (as we learned earlier). In turn, the DispatcherServlet will use Spring’s delegate components for configuration discovery, call request mapping, view resolution, exception handling, and more. Simply put, the user request arrives at the DispatcherServlet, and then it calls other components to handle the user’s request. DispatcherServlet is the process control center of the whole request processing, and the existence of DispatcherServlet reduces the coupling between components.

Each of these functional components has a different top-level interface in the framework, and their implementation classes can be seen as Spring managing special beans to which the DispatcherServlet delegates to process the request and render the appropriate response. Usually these components (interfaces) have default implementations, which means that we don’t need to configure these special beans, but we can also customize their properties and extend or replace them.

The special beans (interfaces, components) that DispatcherServlet will delegate are as follows (from the Spring website) :

HandlerMapping A processor mapper, used to find a Handler capable of handling a request, maps the request to a HandlerExecutionChain object (containing one Handler Handler object and multiple HandlerInterceptor interceptors) object.
HandlerAdapter Processor adapter that helps the DispatcherServlet invoke the Handler to which the request is mapped, but regardless of how the Handler is actually invoked. We will return a ModelAndView object, where Model is a Map structure that holds all the data we returned, and View is the logical view name, ViewName.
HandlerExceptionResolver The exception parser, if it throws an exception during the previous execution of the handler, will follow the exception parser method! In the exception parser, you can map this error to other handlers, HTML error views (error pages), or uniformly throw your own exception.
ViewResolver View resolver, the ViewResolver resolves the logical View name of String type in ModelAndView returned by handler into the physical View name, that is, the specific resource address, and regenerates the corresponding View object. But the actual transaction parsing and data populating work is done by the View itself (view.render method).
LocaleResolver, LocaleContextResolver Locale information can be directly obtained by the front end, and different views can be displayed according to different user regions. For example, different languages and time zones can be set for users in different regions, which supports international views.
ThemeResolver Theme parser, theme is the overall style or style of the system, through the Spring MVC framework provided by the theme (theme) Settings to apply different overall style style, improve user experience. The theme of Spring MVC is a collection of static resources, including styles and images, that control the visual style of your application. Themes also support internationalization, and different areas of the same theme can display different styles.
MultipartResolver MultipartResolver, used to handle upload requests, files can be uploaded using MultipartResolver to parse the upload request file data, convenient and fast file upload!
FlashMapManager Stores and retrieves Flashmaps that can be used to pass properties from one request to another, usually for redirection. This means that flashMaps are mainly used to pass parameters through the redirect, and the FlashMapManager is used to manage these Flashmaps.

Below we will briefly introduce some core components, and does not involve the source code, suitable for Spring MVC beginners!

2 HandlerMapping

2.1 Handler

Handler refers to the Handler, which corresponds to THE C in MVC, also known as Controller. In the Spring MVC framework, there are many implementations of Handler, such as:

  1. Implement the Servlet interface or inherit the HttpServlet classAnd so on, which is the most traditional way, and is almost no longer used after the use of frameworks.
  2. Implement Coltroller interface or inherit Coltroller implementation class.
  3. Implement HttpRequestHandler interface or inherited HttpRequestHandler implementation class.
  4. Marking the@requestMapping annotations and annotations using @RequestMapping as meta-annotations (such as @getMapping, @PostMapping, @putMapping, @deletemapping, @PatchMapping, etc.).

The Handler contains our business code logic!

An implementation of a Controller is encapsulated as a Handler object of the corresponding type. Controllers implemented with @RequestMapping annotations and annotations that use @RequestMapping as meta-annotations are encapsulated as HandlerMethods, with Controller methods stored internally. RequestMapping (@requestMapping) is the most commonly used method. If you add @requestMapping (@requestMapping) or @requestMapping (@requestMapping) as a meta-annotation to a method, the method is treated as a Controller. There is no requirement for the specific class to which the method belongs. Therefore, a Controller class can contain multiple Controller methods, which can handle different requests. This method level Controller implementation saves a lot of class file writing, making the application more lightweight.

There are many types of handlers, but there is no universal interface, so they are used in the source codeObjectType to save.

2.2 HandlerMapping

Spring MVC requires a Handler for each request, so which Handler is used when a request is received? This needs to be found by HandlerMapping.

HandlerMapping is a processor mapper that is called by a DispatcherServlet and is used to find the corresponding Handler based on the request. The request is mapped to a HandlerExecutionChain object (containing a Handler Handler object and multiple HandlerInterceptor interceptors for pre-processing and post-processing) object.

public interface HandlerMapping {

    /** * Returns the HandlerExecutionChain containing the Handler object matching the request and the entire Chain of HandlerInterceptor interceptors. * Can be selected based on any of the request URL, session state, or implementation class selection. * <p> * DispatcherServlet will query all registered HandlerMapping beans for a match or return NULL if none is found. This is not a mistake. * *@returnA HandlerExecutionChain object containing a handler object and all interceptor interceptors, which returns null */ if no mapping is found
    @Nullable
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}
Copy the code

As you can see, the HandlerMapping interface contains the only getHandler method that finds the HandlerExecutionChain through request, HandlerExecutionChain wraps a Handler and a set of Interceptor interceptors.

2.3 Implementation of HandlerMapping

The detailed rules for requesting mappings vary with different implementations of HandlerMapping, where multiple mappers can coexist and be sorted in a Web project. When looking for a mapping, the DispatcherServlet traverses all the HandlerMapping beans registered in the current container to find a match, stopping the search when the first one is found.

If an implementation of HandlerMapping is specified in the configuration file, thenSpring5.2.8. RELEASEVersion will be loaded by defaultBeanNameUrlHandlerMapping, RequestMappingHandlerMapping and RouterFunctionMapping (Spring 5.2 additional support RouterFunctions mapper)These three HandlerMapping. If HandlerMapping is configured manually, the default HandlerMapping is not loaded.

You don’t need to specify HandlerMapping and use the default configuration. Let’s take a look at a common HandlerMapping implementation!

2.3.1 BeanNameUrlHandlerMapping

BeanName way. BeanNameUrlHandlerMapping, using the Controller beanname for map urls to find the corresponding Handler. BeanNameUrlHandlerMapping will only find the implements Coltroller interface or inherit Coltroller implementation class, And the implementation of the HttpRequestHandler interface or inherited HttpRequestHandler implementation class these two ways to implement the Handler.

BeanNameUrlHandlerMapping will default configuration (without manually configure other HandlerMapping), so we only need to configure the Handler.

Annotations are used as follows:

/** * Based on the implementation of the Controller interface Handler **@author lx
 */
@org.springframework.stereotype.Controller("/beanNameUrl")
public class BeanNameUrlController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // Create ModelAndView object
        ModelAndView mv = new ModelAndView();
        // Which page to jump to MVC goes to the view parser
        mv.setViewName("index.jsp");
        returnmv; }}Copy the code

XML is used as follows:

<! Name = '/' --> '/' -->
<bean name="/beanNameUrl" class="com.spring.mvc.controller.BeanNameUrlController"/>
Copy the code

2.3.2 SimpleUrlHandlerMapping

The url. SimpleUrlHandlerMapping: Searches for handlers based on the configured URL path and Controller mapping. Multiple urls can be configured in a centralized manner. SimpleUrlHandlerMapping will only look for implementation classes that implement Coltroller interfaces or inherit from Coltroller, And the implementation of the HttpRequestHandler interface or inherited HttpRequestHandler implementation class these two ways to implement the Handler.

SimpleUrlHandlerMapping is not automatically configured by Spring by default, so it needs to be configured manually.

<! SimpleUrlHandlerMapping -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <! Select * from beanName; select * from beanName;
        <props>
            <prop key="/simpleUrl1">simpleUrlController1</prop>
            <prop key="/simpleUrl2">simpleUrlController2</prop>
            <! -- Configure a generic Handler by * -->
            <! Requests such as /simpleUrl3 /simpleUrl4 will be forwarded to the simpleUrlController3 Handler.
            <prop key="/simpleUrl*">simpleUrlController3</prop>
        </props>
    </property>
</bean>
Copy the code
/ * * *@author lx
 */
@org.springframework.stereotype.Controller
public class SimpleUrlController {

    @org.springframework.stereotype.Controller("simpleUrlController1")
    public class SimpleUrlController1 implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("simpleUrlController1");
            // Create ModelAndView object
            ModelAndView mv = new ModelAndView();
            // Which page to jump to MVC goes to the view parser
            mv.setViewName("index.jsp");
            returnmv; }}@org.springframework.stereotype.Controller("simpleUrlController2")
    public class SimpleUrlController2 implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("simpleUrlController2");
            // Create ModelAndView object
            ModelAndView mv = new ModelAndView();
            // Which page to jump to MVC goes to the view parser
            mv.setViewName("index.jsp");
            returnmv; }}/** * Based on the HttpRequestHandler interface Handler */
    @org.springframework.stereotype.Controller("simpleUrlController3")
    public class SimpleUrlController3 implements HttpRequestHandler {
        @Override
        public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
            System.out.println("simpleUrlController3");
            response.sendRedirect("index.jsp"); }}}Copy the code

2.3.3 RequestMappingHandlerMapping

Annotation mode. A HandlerMapping RequestMappingHandlerMapping is the most commonly used, because it supports search by @ RequestMapping annotations or @ RequestMapping as yuan notes the way of the Handler. Since spring3.1 version, abolishing the DefaultAnnotationHandlerMapping use.

RequestMappingHandlerMapping in constructing HandlerExecutionChain objects, object will be internally within the handler property type set to HandlerMethod types.

RequestMappingHandlerMapping will default configuration (without manually configure other HandlerMapping), so we only need to configure the Handler. Not to mention Handler, which is so common, In terms of the most common @requestMapping annotations on methods and annotations that use @requestMapping as meta-annotations (e.g. @getMapping, @postMapping, @putMapping, @deletemapping, PatchMapping) way!

3 HandlerAdapter

Processor adapter. Help the DispatcherServlet call to the Handler found, but regardless of how the Handler is actually called.

After HandlerMapping finds the corresponding Handler, we need to call the Handler. However, as we said before, there are many forms of Handler implementation. If we use if else to determine the type and call it, we may need to modify the previous code at any time, which does not comply with the open and close principle. throughHandlerAdapter for HandlerTo execute, this isAdapter modeBy extending the HandlerAdapter, you can execute on more types of processors without modifying the source code.

When HandlerMapping obtains a Handler for executing the request, DispatcherServlte calls all registered HandlerAdapters in sequence. If the current HandlerAdapter is able to execute on the current Handler, This will greatly reduce the difficulty of calling the Handler directly through the DispatcherServlet. This will also make the program more extensible.

HandlerAdapter calls Handler methods through reflection, but it doesn’t care how the method is executed! After execution, the HandlerAdapter returnsModelAndViewObject, where Model is a Map structure that holds all the result values we return to the request, and view is the logical view name (ViewName).If the rendering view is not required, null may be returned, such as an Application/JSON request.

The interface method of HandlerAdapter is as followssupportsMethod to determine whether to assist the handler, passhandleMethod executes on the Handler.

public interface HandlerAdapter {

    /** * Given a handler instance, returns whether the HandlerAdapter can support it. * Usually a HandlerAdapter of a type supports only one type of handler. * *@paramHandler Specifies the handler handler *@returnWhether this HandlerAdapter can use the given handler */
    boolean supports(Object handler);


    /** * use the given handler to process the request. * *@paramRequest Indicates the current HTTP request *@paramResponse Current HTTP response *@paramHandler Indicates the handler to be used. This object must previously be passed to the Supports method of this interface, which must return true *@returnA ModelAndView ModelAndView object with the name of the view and the required model data, returning null */ if the request has been handled directly
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    // Get the last change time of the current request, mainly used for the browser to determine whether the current request has been modified,
    // To determine whether the previously cached results can be used directly

    /** * Same contract as for HttpServlet's getLastModified method. Can simply return -1 if there's no support in the Handler class. * serves the same purpose as the getLastModified method of HttpServlet. If there is no support in handler, simply return -1. * *@paramRequest Indicates the current HTTP request *@paramHandler Specifies the handler * to use@returnGiven the handler's last modified value */
    long getLastModified(HttpServletRequest request, Object handler);

}
Copy the code

Handler execution is a complex process, which may involve conversion and encapsulation of parameter types, JSON return serialization and serialization, etc. We’ll talk about that later!

3.1 Implementation of HandlerAdapter

Usually a type of Handler requires a corresponding HandlerAdapter.

  1. RequestMappingHandlerAdaptermainlyAdaptive annotation processorThe annotation handler is the method handler that we often use the @RequestMapping annotation and its meta annotation.
  2. HttpRequestHandlerAdapterStatic resource handlers are class handlers that implement HttpRequestHandler or HttpRequestHandler subclasses and handle requests for static resources accessed via Spring MVC.
  3. SimpleControllerHandlerAdapterController is a Controller processing adapter for processors that implement the Controller interface or a subclass of the Controller interface.
  4. SimpleServletHandlerAdapterServlet processing adapter, which ADAPTS to processors that implement Servlet interfaces or subclasses of servlets. Not only can we configure servlets in web.xml, but we can also configure servlets using SpringMVC, which is rarely used. And the default Spring MVC adapter doesn’t have it.

Spring5.2.8. RELEASEIn the version, the default HandlerAdapter isHttpRequestHandlerAdapter, SimpleControllerHandlerAdapter, RequestMappingHandlerAdapter, And HandlerFunctionAdapter (a processor adapter added to Spring 5.2 to support RouterFunctions).

Also, HandlerMapping is usually not specified and the default configuration is used!

4 HandlerExceptionResolver

The exception parser, if it throws an exception during the previous execution of the handler, will follow the exception parser method! Note that HandlerExceptionResolver can only handle exceptions that are thrown before the Handler completes execution. It cannot handle exceptions that are thrown during steps after the Handler completes execution, such as during page rendering.

The exception resolver can define various strategies for resolving exceptions, perhaps mapping requests to other handlers, HTML error views (error pages), or uniformly throwing their own exceptions. A custom exception parser must implement the HandlerExceptionResolver interface, implement the resolveException method, and then configure the exception parser into the container!

A large, well-developed project usually has its own exception resolver, which we’ll talk about later!

There is only one HandlerExceptionResolverresolveExceptionMethod, which returns aModelAndView, which can contain the data to be returned and the view name, that is, for example, inHandlerAdapter.handle()Method throws an exception during execution, which in turn executesHandlerExceptionResolver.resolveException()Method, which will eventually return and render the return value of the method.

public interface HandlerExceptionResolver {

    /** * Attempts to resolve a given exception thrown during handler execution, Return a ModelAndView that represents a particular error (such as a uniform exception page) * <p> * The returned ModelAndView may be an empty cashed (modelAndView.isEmpty () returns true) * indicating that the exception has been successfully resolved, But no view is rendered, for example by setting a status code. * *@paramRequest Indicates the current HTTP request *@paramResponse Current HTTP response *@paramHandler Handler * executed@paramException thrown by ex during handler execution *@returnCorresponding ModelAndView to be forwarded to, or NULL */
    @Nullable
    ModelAndView resolveException(
            HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);

}
Copy the code

5 ViewResolver

5.1 the View

The Spring MVC framework provides support for many types of View views, including JstlView, FreemarkerView, PdfView, etc. The most commonly used View is JSP, which corresponds to InternalResourceView.

View object saves the URL path of the physical View resource resolved by the logical View nameView.renderMethod can fill (render) the returned model data (data that needs to be displayed) to the corresponding position in the corresponding physical view, and finally render the page through response response to the client (for example, return the HTML text Mosaic).

However, if more strictly, views are more used to prepare the model data before handing it over to a particular View technology than to actually render the View, which still relies on its own View rendering technology for that type of View!

For a simple JSP View, such as InternalResourceView, the first thing to do when rendering is to store the Model data in the Request field property, RequestDispatcher then forwards the request include or forward directly to the JSP resource corresponding to the physical view path URL. The include/forward method is the original Servlet API we’ve seen before. Ultimately, the response is given to the user (in the case of a JSP, the JSP is rendered and output as HTML text in Response).

As you can see from the rendering and output of the JSP View above, the View does nothing but encapsulate and prepare the data (such as storing model data in the Request field property), and does nothing to actually render the View (just call the include/ Forward method). For the JSP View, The actual View rendering and data filling and returning responses still rely on primitive JSP technology, independent of Spring MVC, independent of the View.

public interface View {

    / * * *@returnContent-type A character string that may contain charset */
    @Nullable
    default String getContentType(a) {
        return null;
    }

    /** * Render the current view based on the given model data **@paramModel A Map with the name as the key and value as the value *@paramRequest Current request *@paramResponse The response object */
    void render(@NullableMap<String, ? > model, HttpServletRequest request, HttpServletResponse response)
            throws Exception;
}
Copy the code

5.2 ViewResolver

View parser, ViewResolver parsed the logical View name of String type in ModelAndView returned by handler into the physical View name, that is, the specific resource URL address, and generated the corresponding View object. Specific View rendering and populate the data work completed by View themselves, actually is only in View of the data preparation, in the end is still by invoking the corresponding View API for View rendering and populate the data, and these methods are various views templates or API specification itself, is not the View.

There is only one ViewResolver interfaceresolveViewNameMethod to find and resolve the corresponding physical view URL location based on the given logical viewName viewName and locale (for internationalization)ViewView object!

public interface ViewResolver {

    /** * parses the given viewName to a View View. * <p> * *@paramViewName Name of the view to be resolved *@paramLocale Resolves the view's locale, used to support internationalization *@returnView object, which returns null * if no corresponding View is found@throwsException If the View cannot be resolved (usually a problem when creating the actual View object) */
    @Nullable
    View resolveViewName(String viewName, Locale locale) throws Exception;

}
Copy the code

Spring provides us with a number of default implementations of view parsers, such as:

  1. BeanNameViewResolver: Resolves the logical view name to the bean name in the current application context, then looks up the bean instance of the corresponding name and returns. That is, the bean with the corresponding name should bea View object.
  2. FreeMarkerViewResolver: Resolve the logical view name to a FreeMarkerView object, which is simply support for the FreeMarker template!
  3. InternalResourceViewResolver:One of the most widely used view parsers. Resolve the logical view name into an InternalResourceView object, and InternalResourceView stores the returned Model properties into the corresponding Request property. The request forword is then sent to the target URL on the server side via the RequestDispatcher. We know that/web-INF/cannot be requested directly. For security reasons, we usually put resources such as JSP files in web-INF directory. The InternalResourceViewResolver automatic forwarding mechanism can be both safe and convenient forward (no need to write the code) to access these resources.

The default ViewResolver isInternalResourceViewResolverThe specified ViewResolver also supports ordering!

5.3 ViewResolver configuration

Many components of Spring MVC don’t need to be configured, but ViewResolver probably does! Usually we configure InternalResourceViewResolver like this:

<! -- Configure the view parser -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <! -- To access the relative directory of the file -->
    <property name="prefix" value="/WEB-INF/pages/"/>
    <! -- file name extension -->
    <property name="suffix" value=".jsp"/>
</bean>
Copy the code

For projects that do not have a front and back end separation, views such as JSP, CSS, and JS files are usually placed in the Web-INF directory. Since the contents of /WEB-INF/ cannot be accessed by direct request, they need to be forwarded internally by the server. So we usually configuration InternalResourceViewResolver.

/ web-INF /pages/index.jsp; / web-inf /pages/index.jsp; / web-inf /pages/index.jsp The logical view name we return must be “/ web-INF /pages/index.jsp”.

At this point we can like the above case set the prefix and suffix attribute of InternalResourceViewResolver, prefix said a prefix path view files, while suffix said view file suffix. Now we return to the logical view can direct return to the “index”, analytical automatically InternalResourceViewResolver in joining together for “/ WEB – INF/pages/index. The JSP”, this code is more concise.

6 Spring MVC execution flow

  1. Requests arrive at the DispatcherServlet.
  2. Determine the handler for the current request. Gethandlerexecutionchain by iterating through handlerMappings, calling the getHandler method of each HandlerMapping in turn. If a HandlerMapping getHandler method returns a value that is not null, the HandlerMapping getHandler method returns a value that is not null. forRequestMappingHandlerMappingThe handler he returns isHandlerMethod.
    1. The handler found is actually oneHandlerExecutionChainObject, which contains theThe actual handler and the chain of HandlerInterceptor interceptors applicable to the current handler.
    2. If no handler is found (handler returns NULL), it usually returns404Response code or throwNoHandlerFoundExceptionThe exception.
  3. The handler adapter for the current request — the HandlerAdapter — is determined from the handler. Call each HandlerAdapter in turn by iterating through handlerAdapterssupportsThe supports method returns true as long as there is a HandlerAdapter in that HandlerAdapter. The supports method does not continue the search. If it is not found in all handlerAdapters, it simply throwsServletException. forHandlerMethodAnd its adapter isRequestMappingHandlerAdapter.
  4. Sequentially applies the PreHandle method to all interceptors in the interceptor chainIf either interceptor fails, the request is not processed and is executed directly from the current interceptor in reverse orderafterCompletionMethod, finallyreturn. If they all pass, thenContinue subsequent processing.
  5. Executing the given handler through a HandlerAdapter returns a ModelAndView result object.
    1. The actual workflow of different handlers is very different forHandlerMethodFor it to be throughRequestMappingHandlerAdapterThe final destination will attempt to execute the corresponding@ ReuqestMapping method, business logic, which also includesParameter deserialization, data binding, validation, return value processing, serializationAnd so on.
    2. ModelAndViewThe object’sModelThe part is the model data returned by the business, which is a map,ViewPart is the logical view name of the view, i.eViewName.
    3. The returned ModelAndView is used to render the view, or if no rendering view is requirednullThis is usually the case where the returned data has been serialized as a JSON string and written to response, for exampleApplication/json request(Usually projects with separate front and back ends).
  6. When handler completes normal processing, the postHandle postprocessing method for all interceptors in the interceptor chain is applied in reverse order.
  7. Handle exceptions thrown during the execution of a handler (if any), will be determined by registered HandlerExceptionResolvers handling errors ModelAndView, whereby we can to the abnormal forward to unified configuration error page!
  8. If the ModelAndView is not null, the view is rendered against the ModelAndView (either from production or from error handling). (For projects with separate front and back ends, this is usually JSON-basedApplication/json request, so there is no render view step.
    1. The ViewResolver may first be called to attempt to resolve the given View name into a View object (to be rendered, which holds the URL path of the physical View resource resolved by the logical View name viewName).
    2. thenCall the Render method of the View itself to do the actual rendering work. However, if more strictly, views are more used to prepare the model data before handing it over to a particular View technology than to actually render the View, which still relies on its own View rendering technology for that type of View!
      1. For a simple forward request or include request, if the target is a JSP View, the View isInternalResourceViewWhen rendering, the model data is stored in the request domain properties first and then passed请求转发;分派请求Directly requestincludeContaining orforwardForward to the JSP resource corresponding to the physical view path URL, and include/ Forward methods are the ones we’ve seen beforeThe original Servlet API, and ultimately respond to the user via response (in the case of a JSP, render the JSP and output the RESPONSE as HTML text).
      2. As you can see from the rendering and output of the JSP View above, the View does nothing but encapsulate and prepare the data (such as storing model data in the Request field property), and does nothing to actually render the View (just call the include/ Forward method). For the JSP View, The actual View rendering and data filling and returning responses still rely on primitive JSP technology, independent of Spring MVC, independent of the View.
  9. Finally, whether an exception is thrown on success or failure of the request processing, the afterCompletion processing methods of all interceptors in the chain of interceptors are applied in reverse order, indicating that the request has been processed.

If you don’t need to render the given model and View, then you don’t need the ViewResolver and View work, i.e. step 8. For example, if the returned result is JSON data, when the Handler executes the Handle method, that is, step 5, the JSON result returned by the execution has been written into the response body, and the returned ModelAndView is null after the execution.

Therefore, if the project is separated from the front and back end, unified use of JSON data interaction, then the presentation layer is still MVC pattern, but usually Model and View are not used, the presentation layer is also called the Controller layer!

The steps above are just the general steps! There are a few details that are not covered, such as the fact that if JSON data interaction is supported, the Handler will first convert the JSON data to an object during execution and then convert the returned object to JSON data after execution. Later when we learn the Spring MVC source, we will be more clear!

In addition, when HandlerAdapter executes handler (handle method), it also involves data conversion, formatting and verification related to request and response, such as JSON serialization and deserialization, data type conversion, parameter condition verification, method parameter encapsulation, etc. The specific logic is very complicated!

For REST-style requests and responses, the core class is HttpMessageConverter, which performs the transformation from the request body to the request method parameters and from the return result to the response body.

7 Default MVC component configuration

The implementation of the various base beans listed in the table above can be configured in the project configuration file. The DispatcherServlet will check for each particular bean in the current WebApplicationContext container. If a particular bean is not configured manually, The DispatcherServlet will load in org \ springframework \ web \ servlet \ DispatcherServlet properties in the configuration file type of the bean’s default configuration, otherwise not loaded.

By default, these components are initialized when the container is created in the onRefresh() method of the DispatcherServlet and are configured to be stored in the corresponding properties within the DispatcherServlet instance for subsequent direct use! Note also that the auto-loaded beans are only stored in the collection properties within the DispatcherServlet and are not managed by the Spring container!

inSpring 5.2.8. RELEASEVersion,DispatcherServlet.propertiesThe configuration is as follows:

# Default implementation classes for DispatcherServlet's strategy interfaces. # Used as fallback when no matching beans are found in the DispatcherServlet context. # Not meant to be customized by application developers. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ org.springframework.web.servlet.function.support.RouterFunctionMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.Exception HandlerExceptionResolver,\ org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNam eTranslator org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManagerCopy the code

It should be noted that throughDispatcherServlet.propertiesThe default loaded component only creates the object instance, provides only the most basic MVC functionality and does not activate the other default configurations, whereas if passedThe @enableWebMVC annotation or the < MVC: Annotation-driven /> tag enables the MVC configurationAfter that, in addition to registering these components, some default configurations are loaded and custom configurations are supported.

For example, if MVC configuration is not enabled, THEN MVC is not supportedapplication/jsonRequest and response (even with Jackson depends on the will not automatically registered MappingJackson2HttpMessageConverter), also will not be able to provide a restful request, response, and exception handling, there is no default conversionService!

Related articles:

  1. spring.io/
  2. Spring Framework 5.x learning
  3. Spring Framework 5.x source code

If you need to communicate, or the article is wrong, please leave a message directly. In addition, I hope to like, collect, pay attention to, I will continue to update a variety of Java learning blog!