Detailed explanation of the complete process of Spring MVC request processing
1. Text description of the process
When an HTTP request arrives on the server, the following process will go through:
Filter chain processing (entry)
- The request first passes through the Filter link
- Each Filter performs pre-processing of the doFilter method in the defined order
- Filter passes the request to the next Filter by calling()
DispatcherServlet receives requests
- After all Filters are processed, the request arrives at the DispatcherServlet
- As the front-end controller, DispatcherServlet handles all requests in a unified manner
Looking for Handler
- DispatcherServlet calls getHandler method
- Iterate through all HandlerMappings and find the Handler that matches the current URL
- After finding the Handler, encapsulate the Handler and the corresponding interceptor into HandlerExecutionChain object
Get HandlerAdapter
- Iterate through all HandlerAdapters according to the type of Handler
- Find HandlerAdapter that supports this Handler type
- HandlerAdapter is used to call Handler and process parameters, return values, etc.
Interceptor pre-processing
- Call the preHandle method of all interceptors in HandlerExecutionChain in order
- If the preHandle of either interceptor returns false, interrupt request processing
- The afterCompletion method of the executed interceptor is triggered when interrupted
Handler handles requests
- Call Handler (Controller method) through HandlerAdapter
- HandlerAdapter is responsible for parameter analysis and type conversion
- Handler executes business logic and returns processing results
Interceptor post-processing
- After the Handler execution is completed, the postHandle method of all interceptors is called in reverse order.
- The view has not been rendered yet
View rendering
- View rendering based on the results returned by Handler
- If it is @RestController, convert the return value to JSON/XML and other formats
- If it is a traditional @Controller, parse the view name and render the view
Interceptor completes processing
- After the view rendering is completed, call the afterCompletion method of all interceptors in reverse order.
- AfterCompletion will be executed regardless of whether there are any exceptions during the process.
Filter chain processing (export)
- The response will pass through the Filter chain in the opposite order as to the request being processed
- Each Filter performs post-processing of the doFilter method
- The final response is returned to the client
2. Detailed explanation of key components
2.1 HandlerMapping
// Core data structurepublic class RequestMappingHandlerMapping { // Save the mapping relationship between URL and processor method private final Map<RequestMappingInfo, HandlerMethod> mappingLookup; } // Mapping examplemappingLookup = { RequestMappingInfo{ patterns=/users/{id}, // URL pattern methods=GET, // HTTP method params=[], // Request parameters headers=[] // Request header } -> HandlerMethod{()} }
2.2 HandlerExecutionChain
public class HandlerExecutionChain { // Handler itself (such as Controller's method) private final Object handler; // List of interceptors associated with Handler private List<HandlerInterceptor> interceptors; }
2.3 HandlerAdapter
// Methods to handle @RequestMapping annotationpublic class RequestMappingHandlerAdapter implements HandlerAdapter { public ModelAndView handle(request, response, handler) { // 1. Parsing the request parameters Object[] args = resolveParameters(request, handler); // 2. Call Controller method Object returnValue = invokeMethod(handler, args); // 3. Process the return value return processReturnValue(returnValue); } }
2.4 View Rendering
// 1. @RestController (JSON rendering)@GetMapping("/api/user") public User getUser() { return user; // Automatically convert to JSON} // 2. @Controller (HTML rendering)@GetMapping("/user") public String user(Model model) { ("user", user); return "userView"; // parse into a specific view}
3. Interceptor execution process
3.1 Interceptor definition
public class LogInterceptor implements HandlerInterceptor { @Override public boolean preHandle(request, response, handler) { ("LogInterceptor - preHandle"); return true; } @Override public void postHandle(request, response, handler, mv) { ("LogInterceptor - postHandle"); } @Override public void afterCompletion(request, response, handler, ex) { ("LogInterceptor - afterCompletion"); } }
3.2 Example of execution order
Filter1 - Request processing Filter2 - Request processing LogInterceptor - preHandle SecurityInterceptor - preHandle ControllerMethod execution SecurityInterceptor - postHandle LogInterceptor - postHandle View rendering SecurityInterceptor - afterCompletion LogInterceptor - afterCompletion Filter2 - Response processing Filter1 - Response processing
3.3 Interceptor calling process
// 1. preHandle call (positive order)for (HandlerInterceptor interceptor : interceptors) { if (!(request, response, handler)) { triggerAfterCompletion(request, response, handler, null); return false; } } // 2. PostHandle call (reverse order)for (int i = - 1; i >= 0; i--) { interceptors[i].postHandle(requestresponse, handler, mv); } // 3. AfterCompletion call (reverse order)for (int i = - 1; i >= 0; i--) { interceptors[i].afterCompletion(request, response, handler, ex); }
This is the end of this article about Spring MVC core components and request processing process. For more related Spring MVC request processing content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!