A lot of people use SpringMVC, but they don’t know how it handles requests. When we learn something, understanding it makes it easier to use it. Let’s take a look at how SpringMVC handles requests. ## Request the flow of the way first:The Spring MVC framework is also request-basedWeb frameworkThe front-end controller pattern is used to provide a centralized request processing mechanism. All requests are designed to be processed by a single handler and then distributed to the corresponding page controller (action/handler) for processing according to the request mapping rules. Let’s take a look at the Spring MVC request process as a whole: 1. First, the user sends a request, which is captured by the SpringMVC front-end controller (DispatherServlet). 2. The front-end controller (DispatherServlet) parses the REQUEST URL to obtain the request URI and invokes HandlerMapping according to the URI. 3. The front-end controller (DispatherServlet) obtains the returned HandlerExecutionChain (including the Handler object and its corresponding interceptor); 4. DispatcherServlet selects an appropriate HandlerAdapter based on the HandlerExecutionChain obtained. (Note: If the HandlerAdapter is successfully obtained, execution of the interceptor’s preHandler(…) begins at this point.) Methods); 5. The HandlerAdapter ADAPTS and executes the requested Handler. The HandlerAdapter extracts the model data from the Request, populates the Handler entry parameter, and starts executing Handler (Controller). During the entry process of populating the Handler, Spring does some additional work, depending on the configuration: HttpMessageConveter: Converts the request message (such as Json, XML, etc.) into an object, which is converted into the specified response information; Data transformation: Data transformation of the request message. Such as String to Integer, Double, and so on; Data formatting: converting a string to a formatted number or date, etc. Data validation: verifies the validity of the data (length, format, etc.) and stores the validation results in BindingResult or Error); 6. When Handler completes, it returns a ModelAndView to the HandlerAdaptor. 7. The HandlerAdaptor adapter returns the execution result ModelAndView to the front-end controller; 8. After receiving the ModelAndView, the front-end controller requests the corresponding view parser; 9. View parser parses ModelAndView and returns the corresponding View; 10. Render the view and return the rendered view to the front-end controller; 11. Finally, the front-end controller will respond to the rendered page to the user or client. All requests to SpringMVC projects (except static resources) start with the front-end controller DispatcherServlet configured in the web.xml file:xml <! -- Servlet request dispatcher --> <servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:servlet-context.xml</param-value> </init-param> <! <load-on-startup>1</load-on-startup> </ Servlet > <servlet-mapping> <servlet-name>springMvc</servlet-name> <! <url-pattern>/</url-pattern> </servlet-mapping>The UML inheritance diagram of DispatcherServlet is as follows:Here is the inheritance structure of the blue line: DispatcherServlet–>FrameworkServlet–>HttpServletBean–>HttpServlet–>GenericServlet–>Servlet –>For handling web requests, we all know that we override the service method by inheriting HttpServlet. If we open the DispatcherServlet source code, we do not see the service method we are looking for. You can see that the superclass overrides the HttpServlet service method. ### FrameworkServlet#servicejava /** * Override the parent class implementation in order to intercept PATCH requests. */ @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); if (httpMethod == HttpMethod.PATCH || httpMethod == null) { processRequest(request, response); } else { super.service(request, response); }}From the source code analysis method when the request for the patch request or to null processRequest0 execution method, other what it calls the superclass method of service, we all know, the SpringMVC request most is get | post request is given priority to, HttpServletBean (HttpServletBean)–> HttpServletBean (HttpServletBean); ### HttpServlet#servicejava @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; if (!(req instanceof HttpServletRequest && res instanceof HttpServletResponse)) { throw new ServletException("non-HTTP request or response"); } request = (HttpServletRequest) req; response = (HttpServletResponse) res; service(request, response); } } protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } } The HttpServlet service is overloaded and calls different methods depending on the request type. For example, if the request method is GET request, the HttpServlet service is overloaded and calls doGet request. Httpservlets have doGet implementations, but there are also doGet implementations in inherited subclasses. Which method is called? It’s obvious to call a subclass’s doGet method (object-oriented polymorphism!!). FrameworkServlet# ## FrameworkServlet#doGet &ProcessRequestjava @Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// System startTime long startTime = system.currenttimemillis (); Throwable failureCause = null; . / / the internationalization LocaleContext previousLocaleContext = LocaleContextHolder getLocaleContext (); LocaleContext localeContext = buildLocaleContext(request); / / build ServletRequestAttributes object RequestAttributes previousAttributes = RequestContextHolder. GetRequestAttributes (); ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes); . / / asynchronous management WebAsyncManager asyncManager = WebAsyncUtils getAsyncManager (request); asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor()); // Initialize ContextHolders initContextHolders(Request, localeContext, requestAttributes); try { doService(request, response); } catch (ServletException | IOException ex) { failureCause = ex; throw ex; } catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); } finally {// Restore the original LocaleContext and ServiceRequestAttributes to LocaleContextHolder and RequestContextHolder. For example, Filter resetContextHolders(Request, previousLocaleContext, previousAttributes); if (requestAttributes ! = null) { requestAttributes.requestCompleted(); } logResult(request, response, failureCause, asyncManager); / / release ServletRequestHandlerEvent message, If the request execution success will release publishRequestHandledEvent (request, response, startTime, failureCause); } } // initContextHolders(request, localeContext, requestAttributes); private void initContextHolders(HttpServletRequest request, @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) { if (localeContext ! = null) { LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable); } if (requestAttributes ! = null) { RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable); }}The method does a few things: Internationalize the setup, create a ServletRequestAttributes object, and initialize the context holders. If you want to obtain request or response objects from a method, you can call LocaleContextHolder and then call doService. For doService methods, there is no implementation provided by the FrameworkServlet class, which is implemented by a DispatcherServlet subclass: ### #doService DispatcherServlet Rewrite doService() method:java @Override protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { logRequest(request); // Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. Map<String, Object> attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap<>(); Enumeration<? > attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); }} //Spring context request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); Request. setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeresolver); Request. setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeresolver); // theme request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); // Redirect data if (this.flashMapManager! = null) { FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap ! = null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); } try {// doDispatch(request, response); } finally { if (! WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot ! = null) { restoreAttributesAfterInclude(request, attributesSnapshot); }}}}The entire method looks like this: Handle requests for include tags, put the context in the request properties, put the internationalization parser in the Request properties, put the topic parser in the Request properties, put the topic in the Request properties, ### DispatcherServlet#doDispatch this method is called in the doService method, from the bottom of the design of the entire request processing flow: – Call processDispatchResult – Find the Handler according to the request – find the corresponding HandlerAdapter according to the Handler – handle the Handler with the HandlerAdapter – call processDispatchResult Method to process the results from above (including the View rendered and output to the user)java protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; // Check whether it is an upload request. Yes Upload request parsing is performed. Otherwise, request processedRequest = checkMultipart(request) is returned. multipartRequestParsed = (processedRequest ! = request); HandlerExecutionChain = HandlerExecutionChain = HandlerExecutionChain = HandlerExecutionChain HandlerInterceptor mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; HandlerAdapter ha = getHandlerAdapter(mappedHandler.gethandler ()); // Last-modified String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); // If the data has not changed, return the last data directly. If (new ServletWebRequest(Request, response).checknotModified (lastModified) &&isget) {return; }} return Interceptor's preHandle if (! mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Execute Handler to return ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.gethandler ()); / / for asynchronous processing, direct return the if (asyncManager. IsConcurrentHandlingStarted () {return; } // When the view is empty, set the default view according to the request. For example, the Handler returns void applyDefaultViewName(processedRequest, mv); . / / the implementation of corresponding Interceptor postHandle 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); } // Handle the returned results, including handling exceptions, rendering pages, AfterCompletion processDispatchResult triggers the Interceptor (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); }}}}1. DoDispatcher first checks whether the upload request, if is it converts the request to MultipartHttpServletRequest, and multipartRequestParsed flag is set to true; 2. Use getHandler to obtain HandlerExecutionChain. 3. Process last-Modified of GET and HEAD requests, where it is mainly determined whether last-Modified value is Modified to process and decide whether to use cached data; 4. Call the corresponding Interceptor’s preHandle one by one to intercept the Interceptor. 5. After the interceptor preHandle method is executed, the Handler will use the HandlerAdapter to execute the corresponding Handler (the Controller method is actually executed). After the Handler completes the request, if asynchronous processing is required, the Handler will return the request directly. If asynchronous processing is not required, set the default view when the view is empty, and then execute the corresponding Interceptor’s postHandle. – Handler: Processor, which directly corresponds to C in MVC, also known as Controller layer, has many specific manifestations, including classes and methods (methods are usually the most common), because its definition is Object. All of the @requestMapping methods we annotated in the method can be treated as a Handler, anything that can actually handle the request can be treated as a Handler. – HandlerMapping: SpringMVC handles many requests. Each request requires a Handler. In this case, HandlerMapping is used to search for the request. – HandlerAdapter: adaptors. Different handlerAdapters need to find different handlerAdapters to call the Handler. Just as tools are needed in a factory, handlerAdapters use handleradapters to complete tasks, and HandlerMapping is used to find tools based on what needs to be done. ### DispatcherServlet#processDispatchResult It includes three parts: handling exceptions, rendering pages, and afterCompletion method that triggers the Interceptor. The exceptions that are handled are generated during the process of requesting the doDispatch method.java private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; // If an exception is thrown during the request, handle the exception if (exception! = null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler ! = null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv ! = null); }} // render the page if (mv! = null && ! mv.wasCleared()) { render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isTraceEnabled()) { logger.trace("No view rendering, null ModelAndView returned."); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } // afterCompletion of the Interceptor request, trigger completion if (mappedHandler! = null) { // Exception (if any) is already handled.. mappedHandler.triggerAfterCompletion(request, response, null); }}Render view:java protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = (this.localeResolver ! = null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName ! = null) { // We need to resolve the view name. view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } if (logger.isTraceEnabled()) { logger.trace("Rendering view [" + view + "] "); } try { if (mv.getStatus() ! = null) { response.setStatus(mv.getStatus().value()); } // Render view.render(mv.getModelInternal(), request, response); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "]", ex); } throw ex; }}Today we come to understand the MVC framework MVC core ideas, SpringMVC internal request process analysis and source code level interpretation, so that we can really understand the whole framework from the bottom level of the original appearance of the implementation, and finally to summarize today’s source analysis process with a graph.# # extensionMVC model-View-Controller (MVC) is a well-known design idea based on designing interface applications. It decouples the business logic from the interface by separating the roles of the model, view, and controller in the application. Typically, the model is responsible for encapsulating application data for presentation at the view layer. The view simply presents the data and does not contain any business logic. The controller receives the request from the user and invokes the background service (Service or DAO) to process the business logic. After processing, the back-end business layer may return some data to be displayed in the view layer. The controller collects this data and prepares the model for presentation at the view layer. The core idea of the MVC pattern is to separate the business logic from the interface, allowing them to change individually without affecting each other.view + “]”, ex); } throw ex; }} “” today we come to understand the MVC framework MVC core ideas, SpringMVC internal request process analysis and source code level interpretation, so that we can really understand the whole framework from the bottom level of the original appearance, and finally to summarize today’s source code analysis process. [img-KN38VSZA-1600825578297] ## extensionMVC model-View-Controller (MVC) is a well-known design idea based on designing interface applications. It decouples the business logic from the interface by separating the roles of the model, view, and controller in the application. Typically, the model is responsible for encapsulating application data for presentation at the view layer. The view simply presents the data and does not contain any business logic. The controller receives the request from the user and invokes the background service (Service or DAO) to process the business logic. After processing, the back-end business layer may return some data to be displayed in the view layer. The controller collects this data and prepares the model for presentation at the view layer. The core idea of the MVC pattern is to separate the business logic from the interface, allowing them to change individually without affecting each other. imG-9IG2eIGA-1600825578300

Need video supporting documents or more information + our programmer little sister V: Lezijie007 (add friends when note: B station -LT, do not note refused to add yo)