扩展AbstractAnnotationConfigDispatcherServletInitializer

时间:2016-02-07 20:32:38

标签: java spring spring-mvc configuration component-scan

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 }; 
    }
    .....
}
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() 中返回
  • ConServlet
  • getServletConfigClasses()
  • 中返回 WebConfig

我阅读了文档

getRootConfigClasses()&amp; getServletConfigClasses()用于

  

指定要提供给的@Configuration和/或@Component类。   (他们的差异)

  • getRootConfigClasses()
  • 的根应用程序上下文
  • getServletConfigClasses()
  • 的调度员servlet应用程序上下文

但为什么 ConServlet &amp; WebConfig 做同样的事情(比如初始化视图),也许是我误解了它的人。在简单术语/示例

中,实际上是根上下文和调度程序servlet(我知道这一点)

谢谢!

2 个答案:

答案 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。

Typical context hierarchy in Spring Web MVC
Spring Web MVC(Spring文档)中的典型上下文层次结构

如果您生活在单个Servlet世界中,则此方案也可能只有一个根上下文:

enter image description here
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,其中包含RepositoryConfigDataSourceEntityManagerFactory等所有数据访问工具。可能如下:

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才需要它们。