After using SpringBoot, we can no longer see the DispatcherServlet directly in use. This article, take you from the initial use of DispatcherServlet to SpringBoot source DispatcherServlet automatic configuration in detail.

Introduction of DispatcherServlet

The DispatcherServlet is an implementation of the front-end controller design pattern, provides a centralized point of access to Spring Web MVC, and is responsible for the assignment of responsibilities, and is seamlessly integrated with the Spring Ioc container to reap all the benefits of Spring.

DispatcherServlet role

DispatcherServlet is mainly used for responsibility scheduling and itself is mainly used for control process. The main responsibilities are as follows:

  • File upload resolution. If the request type is multipart, the file upload resolution is performed by MultipartResolver.
  • Through HandlerMapping, requests are mapped to handlers (returning a HandlerExecutionChain containing one handler and multiple HandlerInterceptor interceptors).
  • Support for multiple types of processors (processors in the HandlerExecutionChain) through a HandlerAdapter;
  • Use ViewResolver to resolve the logical view name to the concrete view implementation.
  • Localization parsing;
  • Render specific views, etc.
  • If an exception is encountered during execution, HandlerExceptionResolver will resolve it.

DispatcherServlet workflow

DispatcherServlet traditional configuration

DispatcherServlet acts as the front controller and is typically configured in a web.xml file. The Servlet intercepts matched requests. The Servlet intercepts matched requests by defining its own rules. The intercepted requests are distributed to the target Controller for processing according to the corresponding rules, which is the first step in configuring Spring MVC.

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/dispatcherServlet-servlet.xml</param-value> 
    </init-param>
</servlet> 
<servlet-mapping>
     <servlet-name>dispatcherServlet</servlet-name>
     <url-pattern>*.do</url-pattern> 
</servlet-mapping>Copy the code

The DospatcherServlet is actually a Servlet (it inherits HttpServlet). Requests handled by the DispatcherServlet must be mapped using urL-mapping in the same web. XML file. This is a standard J2EE servlet configuration.

In the above configuration:

  • Servlet-name specifies the name of the servlet. In this case, dispatcherServlet.
  • Servlet – class is used to define defined above the specific implementation of the servlet class, here is the org. Springframework. Web. Servlet. DispatcherServlet.
  • Init-param is used to define the initialization parameters of the servlet, which specifies that dispatcherservlets-servlet.xml in the WEB-INF folder should be initialized. If spring-mvC.xml is named as servlet-name+”-servlet”, you can omit this initialization parameter (the default spring configuration file is “/ web-INF /[servlet name]-servlet.xml”),Sprin G will process the configuration file. As you can see, Spring’s configuration files can also be placed in other locations, as long as they are specified here. If multiple configuration files are defined, separate them with commas (,).
  • Servlet-mapping defines that all requests ending in.do go through the dispatcher.

When DispatcherServlet is configured, once DispatcherServlet receives a request, DispatcherServlet starts processing the request.

DispatcherServlet processing flow

When the DispatcherServlet is configured, processing begins when the DispatcherServlet receives its corresponding request. The processing process is as follows:

Find the WebApplicationContext and bind it to a property of the request so that the controller and other processors on the processing chain can use the WebApplicationContext. The default attribute called DispatcherServlet. WEBAPPLICATIONCONTEXT_ATTRIBUTE.

Bind the localization parser to the request so that the handler on the processing chain can localize the request (prepare the data, display the view, and so on). If you don’t need local resolution, just ignore it.

Bind the topic resolver to the request so the view can decide which topic to use. If you don’t need a theme, you can ignore it.

If you specify an upload file parser, Spring will check whether there is upload each receives the request file, if it is, the request will be encapsulated into MultipartHttpServletRequest for use by other processors in the processing chain. (Spring’s Multipart (Fileupload) support for more details)

Find the appropriate processor and execute the chain of execution (preprocessor, post processor, controller) associated with that processor to prepare the model data for the view.

If the model data is returned, the view is displayed using the view resolver configured in the WebApplicationContext, otherwise the view is not displayed. The returned data model can be null for a number of reasons, such as the request may have been intercepted by the preprocessor or post-processor, either for security reasons or because the request has already been processed and does not need to be processed again.

DispatcherServlet related source code

Org. Springframework. Web. Servlet. DispatcherServlet doService method in part of the source code:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { // ...... request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext()); / /... }Copy the code

As you can see from the above source, the DispatcherServlet finds the WebApplicationContext(whose implementation class is specified as XmlWebApplicationContext), Bind it to a property (the default is WEBAPPLICATIONCONTEXT_ATTRIBUTE) so that the controller can use the WebApplicationContext.

InitStrategies method source:

protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}Copy the code

As you can see from the code above, the DispatcherServlet will start with the configuration of the Web layer beans we need, such as HandlerMapping, HandlerAdapter, etc., and will give us the default configuration if we don’t have it configured.

DispatcherServlet SpringBoot is automatically configured

DispatcherServlet in Spring automatic configuration in the Boot is done through DispatcherServletAutoConfiguration class.

Take a look at the code for the annotations:

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { . }Copy the code

@autoConfigureOrder Specifies the priority of this automatic configuration. @configuration Specifies that the class is automatically configured. @ ConditionalOnWebApplication specify automatic configuration is based on the SERVLET web applications to be met; ConditionalOnClass specifies that the DispatcherServlet class must exist in the classpath. @ AutoConfigureAfter specify that the automatic configuration must be based on ServletWebServerFactoryAutoConfiguration automatic configuration.

DispatcherServletAutoConfiguration on DispatcherServlet instantiation code is as follows:

@ the Configuration (proxyBeanMethods = false) / / instantiate the Configuration class @ Conditional (DefaultDispatcherServletCondition. Class) / / instantiate the condition: Judging by the class @ ConditionalOnClass (ServletRegistration. Class) / / there are specified ServletRegistration class / / loading HttpProperties and WebMvcProperties  @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class }) protected static class DispatcherServletConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties WebMvcProperties) {// Create DispatcherServlet DispatcherServlet = new DispatcherServlet(); Each configuration / / initializes the DispatcherServlet DispatcherServlet. SetDispatchOptionsRequest (webMvcProperties. IsDispatchOptionsRequest ()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails()); return dispatcherServlet; ConditionalOnBean(multipartresolver.class) @conditionalonmissingbean (name = ConditionalOnMissingBean DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) public MultipartResolver multipartResolver(MultipartResolver resolver) {  // Detect if the user has created a MultipartResolver but named it incorrectly return resolver; }}Copy the code

Inner class DispatcherServletConfiguration also needs to meet the specified conditions to initialize, specific see the comments in the code.

The dispatcherServlet method has implemented the instantiation of dispatcherServlet and set the basic parameters. The contrast to the traditional configuration is that of the DispatcherServlet in web.xml.

The multipartResolver method is used to initialize the resolver used for uploading files. If the user-defined multipartResolver name is not “multipartResolver”, Use this method to change it to multipartResolver, which is equivalent to renaming.

Including annotations DispatcherServletConfiguration @ Conditional limit must satisfy the matching conditions of DefaultDispatcherServletCondition definition will automatically configure. While DefaultDispatcherServletCondition class for internal same class.

@Order(Ordered.LOWEST_PRECEDENCE - 10) private static class DefaultDispatcherServletCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { ConditionMessage.Builder message = ConditionMessage.forCondition("Default DispatcherServlet"); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); List<String> dispatchServletBeans = Arrays .asList(beanFactory.getBeanNamesForType(DispatcherServlet.class, false, false)); if (dispatchServletBeans.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) { return ConditionOutcome .noMatch(message.found("dispatcher servlet bean").items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)); } if (beanFactory.containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) { return ConditionOutcome.noMatch( message.found("non dispatcher servlet bean").items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)); } if (dispatchServletBeans.isEmpty()) { return ConditionOutcome.match(message.didNotFind("dispatcher servlet beans").atAll()); } return ConditionOutcome.match(message.found("dispatcher servlet bean", "dispatcher servlet beans") .items(Style.QUOTE, dispatchServletBeans) .append("and none is named " + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)); }}Copy the code

The core function of this class, summed up, is to verify that a dispatcherServlet named “dispatcherServlet” already exists in the Spring container. If not, the condition is met.

There is also an inner class for instantiating a ServletRegistrationBean in this auto-configuration class:

@Configuration(proxyBeanMethods = false) @Conditional(DispatcherServletRegistrationCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) @Import(DispatcherServletConfiguration.class) protected static class DispatcherServletRegistrationConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME) @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {// Register dispatcherServlet as servlet with ServletRegistrationBean, Then the servlet will take effect. DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath()); // Set the name to dispatcherServlet registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); // Set the loading priority. The default value is -1. Exists in WebMvcProperties class registration. SetLoadOnStartup (WebMvcProperties. GetServlet () getLoadOnStartup ()); multipartConfig.ifAvailable(registration::setMultipartConfig); return registration; }}Copy the code

DispatcherServletRegistrationConfiguration class which is the core functions of registered dispatcherServlet enforced and set some initialization parameters.

Among them, the DispatcherServletRegistrationBean inherited from ServletRegistrationBean, mainly provide service for DispatcherServlet. DispatcherServletRegistrationBean DispatcherServlet and provides information on the registration Servlet and publicly DispatcherServletPath function.

Spring Boot does the configuration we did in web.xml using the auto-configuration class above. That’s what makes it convenient.

Reference article:

https://www.cnblogs.com/wql025/p/4805634.html

https://juejin.cn/post/6844903917487128583

SpringBoot DispatcherServlet

Spring Technology Video

CSDN Academy: Spring Boot Video Tutorial family Barrel


Program new horizon