58

扩展时getServletConfigClasses()vs 有什么区别。从今天早上开始,我一直在阅读很多资料,但我还没有对这些差异有任何清楚的了解: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;
    }
}

我看到ConServletWebConfig(或多或少)都在做同样的事情,比如初始化视图:

但为什么 :

  • ConServlet返回getRootConfigClasses()
  • WebConfig返回时getServletConfigClasses()

我阅读了文档

getRootConfigClasses ()getServletConfigClasses() 都适用于

指定要提供给.. 的 @Configuration 和/或 @Component 类(它们的区别)

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

但是为什么ConServletWebConfig 做同样的事情(比如初始化视图),也许是我误解了它。实际上是根上下文和调度程序 servlet(我知道这个)简单的术语/示例

谢谢!

4

2 回答 2

114

层次ApplicationContext结构

SpringApplicationContext提供了加载多个(分层)上下文的能力,允许每个上下文专注于一个特定的层,例如应用程序的 Web 层或中间层服务。

使用分层的典型示例之一ApplicationContext是当我们在 Web 应用程序中有多个DispatcherServlets 时,我们将共享一些公共 bean,例如datasources它们之间。这样,我们可以定义一个ApplicationContext包含所有公共 bean 的根和多个WebApplicationContext从根上下文继承公共 bean 的 s。

在 Web MVC 框架中,每个DispatcherServlet都有自己WebApplicationContext的 bean,它继承了 root 中已经定义的所有 bean WebApplicationContext。这些继承的 bean 可以在特定于 servlet 的范围内被覆盖,并且您可以在给定Servlet实例的本地定义新的特定于范围的 bean。

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

如果您生活在一个单一的DispatherServlet世界中,也可能只有一个根上下文用于此场景:

在此处输入图像描述
Spring Web MVC 中的单根上下文(Spring 文档)

说话很便宜,给我看代码!

假设我们正在开发一个 Web 应用程序,我们将使用 Spring MVC、Spring Security 和 Spring Data JPA。对于这个简单的场景,我们至少有三个不同的配置文件。一个WebConfig包含我们所有与网络相关的配置,例如ViewResolvers、Controllers、ArgumentResolvers 等。如下所示:

@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,它包含所有数据访问工具,例如DataSourceEntityManagerFactoryTransactionManager等。它可能如下所示:

@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和来定义一个典型的分层:SecurityConfigWebConfig

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[] { "/" };
    }
}

延伸阅读

ApplicationContextSkaffman在这个答案中解释层次结构方面做得很好,强烈推荐。此外,您可以阅读Spring 文档

于 2016-02-16T19:26:54.313 回答
7

根配置类实际上用于创建特定于应用程序且需要可用于过滤器的 Bean(因为过滤器不是 Servlet 的一部分)。

Servlet 配置类实际上用于创建特定于 DispatcherServlet 的 Bean,例如 ViewResolvers、ArgumentResolvers、Interceptor 等。

首先加载根配置类,然后加载 Servlet 配置类。

根配置类将是父上下文,它将创建一个ApplicationContext实例。Servlet Config Classes 将是父上下文的子上下文,它将创建一个WebApplicationContext实例。

在您的ConServlet配置中,您不需要指定@EnableWebMvcbean InternalResourceViewResolver,因为它们仅在WebConfig.

于 2016-02-16T08:46:54.530 回答