getServletConfigClasses()
与 getRootConfigClasses()
在扩展 AbstractAnnotationConfigDispatcherServletInitializer
时有什么区别。
我从今天早上开始阅读了很多资料,但我还没有对这些差异有任何明确的了解:
请查看以下两种配置:
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 };
}
.....
}
@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 &amp; WebConfig (或多或少)做同样的事情,比如初始化视图:
但为什么:
getRootConfigClasses()
中返回getServletConfigClasses()
我阅读了文档
getRootConfigClasses()&amp; getServletConfigClasses()用于
指定要提供给的@Configuration和/或@Component类。 (他们的差异)
getRootConfigClasses()
getServletConfigClasses()
但为什么 ConServlet &amp; WebConfig 做同样的事情(比如初始化视图),也许是我误解了它的人。在简单术语/示例
中,实际上是根上下文和调度程序servlet(我知道这一点)谢谢!
答案 0 :(得分:88)
ApplicationContext
层次结构 Spring ApplicationContext
提供了加载多个(分层)上下文的功能,允许每个上下文集中在一个特定的层上,例如应用程序的Web层或中间层服务。
使用分层ApplicationContext
的一个典型示例是,当我们在Web应用程序中有多个DispatcherServlet
时,我们将分享一些常见的bean,例如{{1 }} 它们之间。这样,我们可以定义一个包含所有公共bean的根datasources
和从根上下文继承公共bean的多个ApplicationContext
。
在Web MVC框架中,每个WebApplicationContext
都有自己的DispatcherServlet
,它继承了已在根WebApplicationContext
中定义的所有bean。可以在特定于servlet的范围中重写这些继承的bean,并且可以为给定的WebApplicationContext
实例定义新的特定于范围的bean。
Spring Web MVC(Spring文档)中的典型上下文层次结构
如果您生活在单个Servlet
世界中,则此方案也可能只有一个根上下文:
Spring Web MVC(Spring文档)中的单根上下文
假设我们正在开发Web应用程序,并且我们将使用Spring MVC,Spring Security和Spring Data JPA。对于这个简单的场景,我们至少会有三个不同的配置文件。一个DispatherServlet
,其中包含我们所有与网络相关的配置,例如WebConfig
s,ViewResolver
s,Controller
s等。如下所示:
ArgumentResolver
在这里,我定义了一个@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);
}
}
来解决我的原始jsps,基本上是糟糕的人生决定。我们需要ViewResolver
,其中包含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 { ... }
}
和ApplicationContext
以及在其子上下文中添加RepositoryConfig
来定义典型的分层SecurityConfig
:
WebConfig
由于这里只有一个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
添加到根上下文并使servlet上下文为空:
WebConfig
Skaffman在解释此answer中的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[] { "/" };
}
}
层次结构方面表现出色,强烈推荐。另外,您可以阅读Spring Documentation。
答案 1 :(得分:4)
Root Config Classes实际上用于创建特定于应用程序的Bean,并且需要可用于过滤器(因为过滤器不是Servlet的一部分)。
Servlet配置类实际上用于创建特定于DispatcherServlet的Bean,例如ViewResolvers,ArgumentResolvers,Interceptor等。
首先加载Root Config Classes,然后加载Servlet Config Classes。
Root Config Classes将是Parent Context,它将创建一个ApplicationContext
实例。 Servlet配置类将成为父上下文的子上下文,它将创建WebApplicationContext
实例。
在ConServlet
配置中,您无需指定@EnableWebMvc
以及InternalResourceViewResolver
bean,因为只有WebConfig
才需要它们。