扩展 AbstractAnnotationConfigDispatcherServletInitializer 时的 getServletConfigClasses() 与 getRootConfigClasses()
getServletConfigClasses() vs getRootConfigClasses() when extending AbstractAnnotationConfigDispatcherServletInitializer
扩展[=时getServletConfigClasses()
与getRootConfigClasses()
有什么区别16=]。
从今天早上开始我一直在阅读很多资料,但我还没有对这些差异有任何清晰的了解:
请看一下这两个配置:
1).
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { ConServlet.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
....
....
}
ConServlet.class
指的是
@EnableWebMvc
@Configuration
@ComponentScan({ "com" })
@Import({ SecurityConfig.class })
public class ConServlet {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
2).
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
.....
}
WebConfig.class指的是
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "....." })
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
我看到 ConServlet 和 WebConfig(或多或少)都在做同样的事情,比如初始化视图:
但是为什么:
- ConServlet在
getRootConfigClasses()
中返回
- 而 WebConfig 在
getServletConfigClasses()
中返回
我阅读了文档
getRootConfigClasses() & getServletConfigClasses() 都用于
Specify @Configuration and/or @Component classes to be provided to..
(their differences )
getRootConfigClasses()
的根应用程序上下文
-
getServletConfigClasses()
的调度程序 servlet 应用程序上下文
但是为什么 ConServlet 和 WebConfig 做同样的事情(比如初始化视图),也许我误解了它。 simple term/example
中的根上下文和调度程序 servlet(我知道这个)实际上是什么
谢谢!
Root Config 类 实际上用于创建特定于应用程序且需要可用于过滤器的 Bean(因为过滤器不是 Servlet 的一部分)。
Servlet Config 类 实际上用于创建特定于 DispatcherServlet 的 Bean,例如 ViewResolvers、ArgumentResolvers、Interceptor 等。
Root Config 类 将首先加载,然后 Servlet Config 类 将被加载。
Root Config 类 将成为父上下文,它将创建一个 ApplicationContext
实例。其中 Servlet Config 类 将是父上下文的子上下文,它将创建一个 WebApplicationContext
实例。
在您的 ConServlet
配置中,您不需要指定 @EnableWebMvc
以及 InternalResourceViewResolver
bean,因为它们仅在 WebConfig
处需要。
ApplicationContext
层次结构
Spring 的 ApplicationContext
提供了加载多个(分层)上下文的能力,允许每个上下文专注于一个特定的层,例如应用程序的 Web 层或 middle-tier 服务。
使用分层 ApplicationContext
的典型示例之一是当我们在 Web 应用程序中有多个 DispatcherServlet
时,我们将共享一些公共 bean,例如 datasources
他们之间。这样,我们可以定义一个包含所有公共 bean 的根 ApplicationContext
和从根上下文继承公共 bean 的多个 WebApplicationContext
。
在Web MVC框架中,每个DispatcherServlet
都有自己的WebApplicationContext
,它继承了根WebApplicationContext
中已经定义的所有bean。这些继承的 bean 可以在 servlet-specific 范围内被覆盖,并且您可以在给定的 Servlet
实例本地定义新的 scope-specific bean。
Spring Web MVC 中的典型上下文层次结构(Spring 文档)
如果您生活在一个单一的 DispatherServlet
世界中,对于这种情况也可能只有一个根上下文:
Spring Web MVC 中的单根上下文(Spring 文档)
话不多说,给我看代码!
假设我们正在开发一个 Web 应用程序,我们将使用 Spring MVC、Spring 安全和 Spring 数据 JPA。对于这个简单的场景,我们至少有三个不同的配置文件。一个 WebConfig
包含我们所有的 web 相关配置,例如 ViewResolver
s、Controller
s、ArgumentResolver
s 等。类似以下内容:
@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);
}
}
我在这里定义了一个 ViewResolver
来基本上解决我普通的旧 jsps,糟糕的生活决定。我们需要一个 RepositoryConfig
,其中包含所有数据访问工具,例如 DataSource
、EntityManagerFactory
、TransactionManager
等。它可能如下所示:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.so.repository")
public class RepositoryConfig {
@Bean
public DataSource dataSource() { ... }
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... }
@Bean
public PlatformTransactionManager transactionManager() { ... }
}
还有一个 SecurityConfig
,其中包含所有与安全相关的内容!
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }
@Override
protected void configure(HttpSecurity http) throws Exception { ... }
}
为了将所有这些粘合在一起,我们有两种选择。首先,我们可以通过在根上下文中添加 RepositoryConfig
和 SecurityConfig
并在其子上下文中添加 WebConfig
来定义典型的层次结构 ApplicationContext
:
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
因为这里只有一个 DispatcherServlet
,我们可以将 WebConfig
添加到根上下文并使 servlet 上下文为空:
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
进一步阅读
Skaffman 在 answer, which is highly recommended. Also, you can read Spring Documentation.
中很好地解释了 ApplicationContext
层次结构
扩展[=时getServletConfigClasses()
与getRootConfigClasses()
有什么区别16=]。
从今天早上开始我一直在阅读很多资料,但我还没有对这些差异有任何清晰的了解:
请看一下这两个配置:
1).
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { ConServlet.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
....
....
}
ConServlet.class
指的是
@EnableWebMvc
@Configuration
@ComponentScan({ "com" })
@Import({ SecurityConfig.class })
public class ConServlet {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
2).
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
.....
}
WebConfig.class指的是
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "....." })
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
我看到 ConServlet 和 WebConfig(或多或少)都在做同样的事情,比如初始化视图:
但是为什么:
- ConServlet在
getRootConfigClasses()
中返回
- 而 WebConfig 在
getServletConfigClasses()
中返回
我阅读了文档
getRootConfigClasses() & getServletConfigClasses() 都用于
Specify @Configuration and/or @Component classes to be provided to.. (their differences )
getRootConfigClasses()
的根应用程序上下文
-
getServletConfigClasses()
的调度程序 servlet 应用程序上下文
但是为什么 ConServlet 和 WebConfig 做同样的事情(比如初始化视图),也许我误解了它。 simple term/example
中的根上下文和调度程序 servlet(我知道这个)实际上是什么谢谢!
Root Config 类 实际上用于创建特定于应用程序且需要可用于过滤器的 Bean(因为过滤器不是 Servlet 的一部分)。
Servlet Config 类 实际上用于创建特定于 DispatcherServlet 的 Bean,例如 ViewResolvers、ArgumentResolvers、Interceptor 等。
Root Config 类 将首先加载,然后 Servlet Config 类 将被加载。
Root Config 类 将成为父上下文,它将创建一个 ApplicationContext
实例。其中 Servlet Config 类 将是父上下文的子上下文,它将创建一个 WebApplicationContext
实例。
在您的 ConServlet
配置中,您不需要指定 @EnableWebMvc
以及 InternalResourceViewResolver
bean,因为它们仅在 WebConfig
处需要。
ApplicationContext
层次结构
Spring 的 ApplicationContext
提供了加载多个(分层)上下文的能力,允许每个上下文专注于一个特定的层,例如应用程序的 Web 层或 middle-tier 服务。
使用分层 ApplicationContext
的典型示例之一是当我们在 Web 应用程序中有多个 DispatcherServlet
时,我们将共享一些公共 bean,例如 datasources
他们之间。这样,我们可以定义一个包含所有公共 bean 的根 ApplicationContext
和从根上下文继承公共 bean 的多个 WebApplicationContext
。
在Web MVC框架中,每个DispatcherServlet
都有自己的WebApplicationContext
,它继承了根WebApplicationContext
中已经定义的所有bean。这些继承的 bean 可以在 servlet-specific 范围内被覆盖,并且您可以在给定的 Servlet
实例本地定义新的 scope-specific bean。
Spring Web MVC 中的典型上下文层次结构(Spring 文档)
如果您生活在一个单一的 DispatherServlet
世界中,对于这种情况也可能只有一个根上下文:
Spring Web MVC 中的单根上下文(Spring 文档)
话不多说,给我看代码!
假设我们正在开发一个 Web 应用程序,我们将使用 Spring MVC、Spring 安全和 Spring 数据 JPA。对于这个简单的场景,我们至少有三个不同的配置文件。一个 WebConfig
包含我们所有的 web 相关配置,例如 ViewResolver
s、Controller
s、ArgumentResolver
s 等。类似以下内容:
@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);
}
}
我在这里定义了一个 ViewResolver
来基本上解决我普通的旧 jsps,糟糕的生活决定。我们需要一个 RepositoryConfig
,其中包含所有数据访问工具,例如 DataSource
、EntityManagerFactory
、TransactionManager
等。它可能如下所示:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.so.repository")
public class RepositoryConfig {
@Bean
public DataSource dataSource() { ... }
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... }
@Bean
public PlatformTransactionManager transactionManager() { ... }
}
还有一个 SecurityConfig
,其中包含所有与安全相关的内容!
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }
@Override
protected void configure(HttpSecurity http) throws Exception { ... }
}
为了将所有这些粘合在一起,我们有两种选择。首先,我们可以通过在根上下文中添加 RepositoryConfig
和 SecurityConfig
并在其子上下文中添加 WebConfig
来定义典型的层次结构 ApplicationContext
:
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
因为这里只有一个 DispatcherServlet
,我们可以将 WebConfig
添加到根上下文并使 servlet 上下文为空:
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
进一步阅读
Skaffman 在 answer, which is highly recommended. Also, you can read Spring Documentation.
中很好地解释了ApplicationContext
层次结构