Spring MVC request source code process

preface

Introduction to MVC module of Spring official website:

Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, "Spring Web MVC," comes from the name of its source module (spring-webmvc), but it is more commonly known as "Spring MVC".

Spring Web MVC is an original Web framework based on Servlet API, which has been included in the spring framework from the beginning. The official name "spring Web MVC" comes from the name of its source module (spring webmvc), but it is usually called "Spring MVC".

1, From Servlet to spring MVC

The most typical MVC is the pattern of JSP + servlet + javabean.

1.1 traditional Servlet


Disadvantages:
1. Low development efficiency: it is very troublesome to configure servlet mapping under xml (@ WebServlet annotation is supported after servlet 3.0.)

2. Intrusive: you must inherit the parent class and override the method
3. If you want to process the functions of the same business module in a Servlet, it is very troublesome to distribute them to different methods for processing
4. Trouble in parameter parsing: single parameter (conversion type) - > POJO object Json text - > POJO object
5. Trouble in data response: pojo object - > JSON... Content type
6. Jump page trouble: it's troublesome to control the path, it's troublesome to use other templates, it's troublesome to set the coding... And so on

Therefore, spring MVC is encapsulated on the basis of Servlet, which helps me do all these troublesome things for us.

The upgrading of Web framework is a lazy process.

From the initial Servlet to the current spring MVC, SpringBoot, and so on.

2, Spring MVC

2.1 implementation method based on xml:

1. Configure a dispatcher Servlet (web.xml) for the Servlet container

2. Add spring MVC configuration information

  • Inheritance class / implementation interface:
 implements HttpRequestHandler 

Different HandlerMapping

<!--Set the mapping path by setting properties-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
    <props>
        <prop key="httpRequest">simpleController</prop>
    </props>
</property>

<!--BeanNameUrlHandlerMapping Be sure to Controller Set the name of a valid mapping address, such as  @Controller("/xxxx")-->

2.2 annotation method

Configure the mapping of Controller @ Controller and processing method - @ RequstMapping.

In fact, the principle of spring MVC request is very simple: to put it bluntly, a dispatcher Servlet encapsulates the dispatching center of a Servlet, and the dispatching center calls our processing methods for us.

In this process, the dispatching center entrust each component to perform specific tasks, such as mapping the request for the method, parsing the parameters, calling the processing method, responding data and pages, etc.

3, Specific implementation process of spring MVC

Spring MVC is designed around the front-end controller pattern. The central Servlet DispatcherServlet provides unified scheduling for the request processing process, and the actual work is handed over to configurable components for execution. This model is flexible and open. We can customize these components by ourselves to customize our own workflow.

  • Dispatcher servlet: the front-end scheduler, which is responsible for intercepting requests and distributing them to each controller method
  • HandlerMapping: it is responsible for matching according to the requested URL and the configured @ RequestMapping mapping. If it is matched, the Handler (the method of the specific controller) will be returned
  • HandlerAdaper: it is responsible for calling the Handler - specific method - to return the name of the view. The Handler encapsulates it into modelandview (encapsulates the view name and the data of the request field)
  • Viewrelover: find the specific jsp encapsulated in the View object according to the View name and address in ModelAndView
  • View: the client that performs view rendering (converting jsp into html content -- this is the business of Servlet container) and finally responds to it

The whole calling process:
1. The user sends a request to the front-end controller DispatcherServlet

2. The dispatcher servlet receives a request to call the processor mapper HandlerMapping

  • The processor mapper finds the specific processor according to the request url, generates the processor execution chain, and returns the handler execution chain (including the processor object and the processor interceptor) to the dispatcher servlet

3. The DispatcherServlet obtains the processor adapter HandlerAdapter according to the processor Handler and executes a series of operations handled by the HandlerAdapter, such as parameter encapsulation, data format conversion, data verification and so on

4. Execute Processor Handler(Controller, also known as page controller).

  1. The Handler returns ModelAndView after execution
  2. The HandlerAdapter returns the Handler execution result ModelAndView to the dispatcher servlet

5. DispatcherServlet passes ModelAndView to viewrestrover view parser

  • The viewrestrover returns a specific View after parsing

6. DispatcherServlet renders the View (that is, fill the model data model into the View)

7. Dispatcher servlet response user

The whole calling process is actually reflected in doDispatch:
1. The user sends a request to the front-end controller DispatcherServlet

  • Because it is a Servlet, it will first enter the service method - > doget / dopost - > processrequestdoservice - > dodispatch
  • This doDispatch is very important - it reflects the whole request process. Let's take a look at the source code implementation
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
   try {
      
      try {
          // File upload related
         processedRequest = checkMultipart(request);
         multipartRequestParsed = (processedRequest != request);
         
        // The dispatcher servlet receives a request to call the processor mapper HandlerMapping.
        // The processor mapper finds the specific processor according to the request url, generates the processor execution chain, and returns the handler execution chain (including the processor object and the processor interceptor) to the dispatcher servlet.
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) {
            noHandlerFound(processedRequest, response);
            return;
         }

         // 4. The dispatcher servlet obtains the processor adapter HandlerAdapter according to the processor Handler,
         HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

         // Process last modified header, if supported by the handler
         String method = request.getMethod();
         boolean isGet = HttpMethod.GET.matches(method);
         if (isGet || HttpMethod.HEAD.matches(method)) {
            long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
            if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
               return;
            }
         }
         // Front interceptor
         if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            // If false is returned, no subsequent processing will be performed
            return;
         }

         // Execute the HandlerAdapter to handle a series of operations, such as parameter encapsulation, data format conversion, data validation, etc
         // Execute Processor Handler(Controller, also known as page controller).
         // The Handler returns ModelAndView after execution
         // The HandlerAdapter returns the Handler execution result ModelAndView to the dispatcher servlet
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }
         // If there is no view, set the default view json to ignore
         applyDefaultViewName(processedRequest, mv);
         //Rear interceptor
         mappedHandler.applyPostHandle(processedRequest, response, mv);
      }
      catch (Exception ex) {
         dispatchException = ex;
      }
      catch (Throwable err) {
         // As of 4.3, we're processing Errors thrown from handler methods as well,
         // making them available for @ExceptionHandler methods and other scenarios.
         dispatchException = new NestedServletException("Handler dispatch failed", err);
      }
      // DispatcherServlet passes ModelAndView to viewrestrover view parser
      // The viewrestrover returns a specific View after parsing
      // The dispatcher servlet renders the View (that is, fills the View with the model data model).
      // Dispatcher servlet responds to the user.
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
   catch (Exception ex) {
      triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
   }
   catch (Throwable err) {
      triggerAfterCompletion(processedRequest, response, mappedHandler,
            new NestedServletException("Handler processing failed", err));
   }
   finally {
      if (asyncManager.isConcurrentHandlingStarted()) {
         // Instead of postHandle and afterCompletion
         if (mappedHandler != null) {
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
         }
      }
      else {
         // Clean up any resources used by a multipart request.
         if (multipartRequestParsed) {
            cleanupMultipart(processedRequest);
         }
      }
   }

4, HandlerMapping

In the whole process, many components are involved. Each component parses each link, of which HandlerMapping is the most important. It is used to map requests. We will focus on the parsing process and request mapping process of HandlerMapping:

flow chart: https://www.processon.com/view/link/615ea79e1efad4070b2d6707

Request flow chart:

Keywords: Java Spring mvc

Added by imagineek on Thu, 21 Oct 2021 04:16:29 +0300