The above figure shows the process of the response of the spring architecture when the customer request comes. You can see from the figure that the center of the request distribution is the DispatcherServlet class. The task of the DispatcherServlet is to send the request to the Spring MVC controller. A controller is a Spring component that handles requests. In a typical application there may be multiple controllers and the DispatcherServlet needs to know which controller the request should be sent to. So the DispatcherServlet will query one or more handler mappings to determine where the next stop for the request is. The processor mapping will make decisions based on the URL information carried by the request.
Understanding DispatcherServlet and ContextLoadListener
DispatcherServlet requires a WebApplicationContext that inherits from ApplicationContext as a parameter to configure itself. WebApplicationContext is the associate of ServletContext and Servlet. For many applications, a WebApplicationContext is sufficient and can fully function. It is also possible when we have multiple DispatcherServlet and want to share a common bean in this application, so that we can define a root ApplicationContext contains all common beans and
The root WebApplicationContext (root WebApplicationContext) actually already contains the beans that usually contain basics, such as data repostitories and business services that need to be shared by multiple servlet instances. These beans can be inherited and can be overridden (overridden) in a specific servlet, or in a child WebApplicationContext that contains a given servlet locally. The child WebApplicationContext is the Servlet WebApplicaitonContext as shown below.
Explanation in the referenced article below
Spring's
ApplicationContext
provides the capability of loading multiple (hierarchical) contexts, allowing each to be focused on one particular layer, such as the web layer of an application or middle-tier services.One of the canonical examples of using hierarchical
ApplicationContext
is when we have multipleDispatcherServlet
s in a web application and we're gonna share some of the common beans such asdatasources
between them. This way, we can define a rootApplicationContext
that contain all the common beans and multipleWebApplicationContext
s that inherit the common beans from the root context.In the Web MVC framework, each
DispatcherServlet
has its ownWebApplicationContext
, which inherits all the beans already defined in the rootWebApplicationContext
. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a givenServlet
instance
If there is only one DispatcherServlet in the project, then we can move all the beans originally in DispatcherServlet to the parent class Root WebApplicationContext.
Below is a configuration that implements a WebApplicationContext successor.
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { App1Config.class }; } @Override protected String[] getServletMappings() { return new String[] { "/app1/*" }; } }
If the application context is not required to be inherited (the relationship between WebApplicationContext and child WebApplicationContext), then all configurations can be returned through getRootConfigClasses ( ) and getServletConfigClasses ( ) to return null.
In a Servlet 3.0 environment, the container will look in the classpath for a class that implements the javax.servlet.ServletContainerInitializer interface, and if it can find it, it will use it to configure the servlet container. Spring provides an implementation of this interface, named SpringServletContainerInitializer, which in turn looks for classes that implement WebApplicationInitializer and delegates configuration tasks to them. Spring 3.2 introduced a convenient base implementation of WebApplicationInitializer, AbstractAnnotationConfigDispatcherServletInitializer. Because our SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer (which also implements WebApplicationInitializer), when deployed to a Servlet 3.0 container, the container will automatically discover it and use it to configure the servlet context. (In short, it inherits AbstractAnnotationConfigDispatcherServletInitializer, which will form a child WebApplicationContext)
Our own implementation of MyWebAppInitializer has the same effect as the xml file below.
<web-app> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/root-context.xml</param-value> </context-param> <servlet> <servlet-name>app1</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/app1-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app1</servlet-name> <url-pattern>/app1/*</url-pattern> </servlet-mapping> </web-app>
Similarly, if the application context is not required to be inherited (the relationship between WebApplicationContext and child WebApplicationContext), then all configurations can be returned through the "root context", and the parameter contextLocation in the Servlet returns null.
Example to understand DispatcherServlet
If I use Spring MVC, Spring Security and Spring Data JPA to build my application, then I need to know three config files, WebConfig contains web-related configuration, such as ViewResolvers, Controllers, ArgumentResolver, the code is as follows:
@EnableWebMvc @Configuration @ComponentScan(basePackages = "com.so.web") public class WebConfig extends WebMvcConfigurerAdapter { @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Override public void configurePathMatch(PathMatchConfigurer configurer) { final boolean DO_NOT_USE_SUFFIX_PATTERN_MATCHING = false; configurer.setUseSuffixPatternMatch(DO_NOT_USE_SUFFIX_PATTERN_MATCHING); } }
Here we define a ViewResolver, and we need a RepositoryConfig configuration data-related classes, such as DataSource and TransactionManager, and so on.
@Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = "com.so.repository") public class RepositoryConfig { @Bean public DataSource dataSource() { ... } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... } @Bean public PlatformTransactionManager transactionManager() { ... } }
SecurityConfig contains security-related members.
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... } @Override protected void configure(HttpSecurity http) throws Exception { ... } }
Suppose we only have one DispatcherServlet Below we have two configuration methods:
1 public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 2 @Override 3 protected Class<?>[] getRootConfigClasses() { 4 return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class }; 5 } 6 7 @Override 8 protected Class<?>[] getServletConfigClasses() { 9 return new Class<?>[] { WebConfig.class }; 10 } 11 12 @Override 13 protected String[] getServletMappings() { 14 return new String[] { "/" }; 15 } 16 }
or
1 public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 2 @Override 3 protected Class<?>[] getRootConfigClasses() { 4 return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class }; 5 } 6 7 @Override 8 protected Class<?>[] getServletConfigClasses() { 9 return null; 10 } 11 12 @Override 13 protected String[] getServletMappings() { 14 return new String[] { "/" }; 15 } 16 }
ContextLoaderListener
Bootstrap monitors the startup and shutdown of Spring's root WebApplicationContext. In Spring 3.1, ContextLoaderListener supports initializing root WebApplicationContext through ContextLoaderListener(WebApplicationContext).
special bean
DispatcherServlet delegates to some special beans to process requests and return corresponding responses, these