Spring MVC source code analysis (2): The Design and Implementation of a DispatcherServlet SpringMVC

Outline
 
DispatcherServlet SpringMVC is a front controller, MVC architecture is C, the controller implementation, this intercept all requests for web applications, in particular arranged in the servlet web.xml, url-pattern corresponding to " / ", or WebApplicationInitializer after use servlet3.0 to configure the web container when the application starts, it will create and initialize the object instance DispatcherServlet.
 
DispatcherServlet After receiving the request, the information request based uri, find a method corresponding to a controller to process the request. @Controller @RequestMapping and usually a method to determine the class of the unique process controller which requests the corresponding uri class, including information of the path, HTTP request method. Theme also need processing the subject, the localization locale, multipart request, and in response to the map view of View.
 
Based on the above background of the demand, DispatcherServlet need to define the relevant sub-components to perform these functions. Since the Spring ApplicationContext architectural design of which is to support hierarchical, that is, the entire spring application contains a root WebApplicationContext, multiple sub-WebApplicationContext, son WebApplicationContext share the root WebApplicationContext. Each DispatcherServlet can use a separate, only to create and manage this instance is bound DispatcherServlet WebApplicationContext these sub-assemblies.
 
Class design DispatcherServlet
 
A common servlet the DispatcherServlet both servlet specification, defining processing of the request in the service process; passed the WebApplicationContext spring, i.e. the use of beans container mechanism spring, and to manage its associated subassembly the bean, and maintenance in itself rEFERENCE spring subassembly bean container, thereby to facilitate the call. Therefore DispatcherServlet class structure designs, we need to consider these two aspects of the design, as shown:

 

 

As can be seen from the figure, in the DispatcherServlet class inheritance hierarchy, from bottom to top of: DispatcherServlet -> FrameworkServlet -> HttpServletBean.
 
HttpServletBean
Get application associated property value inherited from the HttpServlet, realized EnvironmentAware (injection Environment object) and EnvironmentCapable (Access Environment object) interface, wherein the attribute file Environment mainly from the class path, operating parameters, @ PropertySource annotations and to provide a spring containers access related components, or write to the Environment attribute to access to other components. HttpServletBean main function is to be associated with the servlet init-param, bean properties of the package, and then to save
Among Environment, which can be accessed in the other spring bean container.
 
FrameworkServlet
Inherited HttpServletBean, because typically comprises a separate DispatcherServlet the WebApplication, but only by the ordinary servlet container servletContext spring acquired root WebApplicationContext, so that the bean from which to obtain relevant, so DispatcherServlet class hierarchy, which increases FrameworkServlet layer design. Role is to acquire, create and manage, WebApplicationContext objects DispatcherServlet bound, to complete the creation WebApplicationContext related to: Get xml or WebApplicationInitializer configuration information from contextConfigLocation, create WebApplicationContext according to contextClass, and get ApplicationContextInitializer to initialize the WebApplicationContext, finally calling refresh DispatcherServlet bound to complete the creation of this WebApplicationContext.
 
DispatcherServlet
FrameworkServlet obtained from the WebApplicationContext, then get DispatcherServlet relevant functional sub-assemblies from WebApplicationContext bean, and then maintain a reference in itself. DoService and implement methods using these components to complete functional sub-process and generate the response to the request.
 
Associated with the three
 
In the init method HttpServletBean, the definition initServletBean template method for subclasses to implement, which initServletBean method FrameworkServlet implementation for creating WebApplicationContext, namely call initWebApplicationContext method to complete the creation of WebApplicationContext and define onRefresh template method implemented by subclasses in initWebApplicationContext method wherein onRefresh DispatcherServlet implemented method from the initWebApplicationContext
 
WebApplicationContext bean gets its functional sub-components, stored in a reference to itself in.
 
DispatcherServlet functional sub-assembly

In onRefresh DispatcherServlet method, the acquisition is completed from the corresponding WebApplicationContext bean, assigning a reference to itself among the source to achieve the following:
/**
 * This implementation calls {@link #initStrategies}.
 */
@Override
protected void onRefresh(ApplicationContext context) {
    initStrategies(context);
}

/**
 * Initialize the strategy objects that this servlet uses.
 * <p>May be overridden in subclasses in order to initialize further strategy objects.
 */
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

DispatcherServlet corresponding bean reference as follows: i.e., the core functional components, including the MultipartResolver multipart request processor, the processor LocaleResolver localization, theme (JSP the css style) themeResolver processor, and the request URI mapping HandlerMappings processing method, the request processor adapter handlerAdapters, requests exception handler handlerExceptionResolvers, view name resolver viewNameTranslator, view processor viewResolvers, memory data transfer request flashMapManager.

/** MultipartResolver used by this servlet. */
@Nullable
private MultipartResolver multipartResolver;

/** LocaleResolver used by this servlet. */
@Nullable
private LocaleResolver localeResolver;

/** ThemeResolver used by this servlet. */
@Nullable
private ThemeResolver themeResolver;

/** List of HandlerMappings used by this servlet. */
@Nullable
private List<HandlerMapping> handlerMappings;

/** List of HandlerAdapters used by this servlet. */
@Nullable
private List<HandlerAdapter> handlerAdapters;

/** List of HandlerExceptionResolvers used by this servlet. */
@Nullable
private List<HandlerExceptionResolver> handlerExceptionResolvers;

/** RequestToViewNameTranslator used by this servlet. */
@Nullable
private RequestToViewNameTranslator viewNameTranslator;

/** FlashMapManager used by this servlet. */
@Nullable
private FlashMapManager flashMapManager;

/** List of ViewResolvers used by this servlet. */
@Nullable
private List<ViewResolver> viewResolvers;
InitHandlerMappings achieve focus of concern, primarily obtain HandlerMapping interface class object instance from the WebApplicationContext, acquisition processor then maps the request and the request URI from HandlerMapping method in which a significant implemented as RequestMappingHandlerMapping (packages for: org.springframework. web.servlet.mvc.method.annotation), and this is a process @Controller @RequestMapping, then generate HandlerMethod object implements mapping URI (the URI information is maintained by RequestMappingInfo), specific detailed analysis in subsequent articles.

Request processing DispatcherServlet

As DispatcherServlet front controller, receives all requests (i.e., from a client sends a request to the Tomcat, the Tomcat target application, assigned to DispatcherServlet), defining processing of the request in a logic doService process. Method doService request some processing of the request, i.e. add some attribute, WebApplicationContext DispatcherServlet comprising the current localization processor LocaleResolver, subject processor themeResolver other functional components, which method and which to process controler selection logic, by the sub-method doDispatch achieved, and generates a response in response to the client, the following source code:
/**
 * Process the actual dispatching to the handler.
 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
 * to find the first that supports the handler class.
 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
 * themselves to decide which methods are acceptable.
 * @param request current HTTP request
 * @param response current HTTP response
 * @throws Exception in case of any kind of processing failure
 */
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;

        try {
        
            // muiltpart请求处理,如果是则进行封装加工
            
            processedRequest = checkMultipart (Request); 
            multipartRequestParsed = (processedRequest =! Request); 

            // Get the controler of the method of the request in 
            
            // the Determine Current The Request Handler for. 
            mappedHandler = the getHandler (processedRequest);
             IF (mappedHandler == null ) { 
                noHandlerFound (processedRequest, Response); 
                return ; 
            } 

            // used to define the request processor adapter HandlerAdapter
             // request unitary format of DispatcherServlet
             // i.e. define a uniform template to call different request processors Handler
            // 其中Handler由拦截器链和请求处理方法HandlerMethod组成
            
            // Determine handler adapter for the current request.
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

            // Process last-modified header, if supported by the handler.
            String method = request.getMethod();
            boolean isGet = "GET".equals(method);
            if (isGet || "HEAD".equals(method)) {
                long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                if (newServletWebRequest (Request, Response) .checkNotModified (the lastModified) && isGet) {
                     return ; 
                } 
            } 
            
            // call interceptor chain preHandle respective interceptors pretreated 
            IF (! ) {MappedHandler.applyPreHandle (processedRequest, Response)
                 return ; 
            } 
            
            // actual processing of the request, returns a ModelAndView
             // wherein model representation model, i.e., data contained in the rendering view
             // view is defined to a particular view JSP 
            
            // actually the Invoke Handler. 
            Music Videos = ha.handle (processedRequest, Response, mappedHandler.getHandler ()); 

            IF (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }

            applyDefaultViewName(processedRequest, mv);
            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);
        }
        
        // 对客户端进行响应
        
        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);
            }
        }
    }
}
to sum up
By the above analysis, the DispatcherServlet as a unified framework springMVC front controller needs to receive all of the requests sent to the application, and then when the native promoter, and the request URI has a good load handler mapping, obtaining the corresponding request processor, the actual request processing performed by the request processor.
So based on this, DispatcherServlet requires multiple seeds to complete request processing functional components, since the plurality of applications may be used to receive requests DispatcherServlet, for isolation of the sub-assembly and packaging a plurality of sub-DispatcherServlet many functional components, each using DispatcherServlet a sub-container itself independent spring WebApplicationContext to manage their own sub-functional components. Then share the same root WebApplicationContext (i.e., WEB-INF / applicationContext.xml) to obtain the common components, such as database connection pools.
In these sub-functional components, we need to focus on core HandlerMappings, namely the request and the request URI handler mapping the design components, namely the DispatcherServlet WebApplicationContext is how to generate this mapping, the mapping of design is kind of how, specifically requesting processor What, as we usually use @Controller application code and @RequestMapping defined, these underlying source code is how practical; when a request comes in, DispatcherServlet is how to find from inside. In fact, these issues will need to achieve the IOC spring, that spring-context and implementation of spring-beans package, a detailed analysis in subsequent articles.
 
For more learning materials, can be added to the group: 473 984 645 or under the Fanger Wei code scanning
 

Guess you like

Origin www.cnblogs.com/1013wang/p/11763161.html