java 扩展 AbstractAnnotationConfigDispatcherServletInitializer 时的 getServletConfigClasses() 与 getRootConfigClasses()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35258758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:55:08  来源:igfitidea点击:

getServletConfigClasses() vs getRootConfigClasses() when extending AbstractAnnotationConfigDispatcherServletInitializer

javaspringspring-mvcconfigurationcomponent-scan

提问by Plain_Dude_Sleeping_Alone

What is the difference between getServletConfigClasses()vs getRootConfigClasses()when extending AbstractAnnotationConfigDispatcherServletInitializer. I've been reading a lot sources since this morning but I haven't get any clear understanding on the differences yet :

扩展时getServletConfigClasses()vs 之间有什么区别。从今天早上开始,我一直在阅读很多资料,但我还没有对差异有任何明确的了解:getRootConfigClasses()AbstractAnnotationConfigDispatcherServletInitializer

Please have look at these two configurations :

请看一下这两个配置:

1).

1)。

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {         
        return new Class[] { ConServlet.class }; 
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {                      
        return null;
    }
        ....
        ....    
        }

The ConServlet.classis refering to

指的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).

2)。

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class }; 
    }
    .....
}

the WebConfig.classis refering to

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;
    }
}

I see both ConServlet& WebConfig(more or less) doing the same things like initializating view :

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

But why :

但为什么 :

  • ConServletis returned in getRootConfigClasses()
  • while WebConfigis returned in getServletConfigClasses()
  • ConServlet被返回getRootConfigClasses()
  • WebConfig返回getServletConfigClasses()

I read the documentation

我阅读了文档

both getRootConfigClasses()& getServletConfigClasses()is for

getRootConfigClasses() getServletConfigClasses()是用于

Specify @Configuration and/or @Component classes to be provided to.. (their differences )

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

  • the root application contextfor getRootConfigClasses()
  • the dispatcher servlet application context forgetServletConfigClasses()
  • 根应用上下文getRootConfigClasses()
  • 调度程序 servlet 应用程序上下文getServletConfigClasses()

but why then ConServlet& WebConfigdoing same things (like initizialising view), maybe I'm the one misunderstood it. What's are actually root context and dispatcher servlets (I know this one) in the simple term/example

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

Thank you!

谢谢!

回答by Ali Dehghani

A Bit on ApplicationContextHierarchies

关于ApplicationContext层次结构的一点

Spring's ApplicationContextprovides 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.

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

One of the canonical examples of using hierarchical ApplicationContextis when we have multiple DispatcherServlets in a web application and we're going to share some of the common beans such as datasourcesbetween them. This way, we can define a root ApplicationContextthat contain all the common beans and multiple WebApplicationContexts that inherit the common beans from the root context.

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

In the Web MVC framework, each DispatcherServlethas its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servletinstance.

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

Typical context hierarchy in Spring Web MVC
Typical context hierarchy in Spring Web MVC (Spring Documentation)

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

If you're living in a single DispatherServletworld, it is also possible to have just one root context for this scenario:

如果您生活在一个单一的DispatherServlet世界中,对于这种情况,也可能只有一个根上下文:

enter image description here
Single root context in Spring Web MVC (Spring Documentation)

在此处输入图片说明
Spring Web MVC 中的单根上下文(Spring 文档)

Talk is cheap, Show me the code!

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

Suppose we're developing a web application and we're going to use Spring MVC, Spring Security and Spring Data JPA. For this simple scenario, we would have at least three different config files. A WebConfigthat contains all our web related configurations, such as ViewResolvers, Controllers, ArgumentResolvers, etc. Something like following:

假设我们正在开发一个 Web 应用程序,我们将使用 Spring MVC、Spring Security 和 Spring Data JPA。对于这个简单的场景,我们至少有三个不同的配置文件。AWebConfig包含我们所有与 Web 相关的配置,例如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);
    }
}

Here I'm defining a ViewResolverto resolve my plain old jsps, poor life decisions, basically. We would need a RepositoryConfig, which contains all the data access facilities such as DataSource, EntityManagerFactory, TransactionManager, etc. It probably would be like following:

在这里,我定义了一个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() { ... }
}

And a SecurityConfigwhich contains all the security related stuff!

还有一个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 { ... }
}

For gluing all these together, we have two options. First, we can define a typical hierarchical ApplicationContext, by adding RepositoryConfigand SecurityConfigin root context and WebConfigin their child context:

为了将所有这些粘合在一起,我们有两种选择。首先,我们可以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[] { "/" };
    }
}

Since we have a single DispatcherServlethere, we can add the WebConfigto the root context and make the servlet context empty:

由于我们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[] { "/" };
    }
}

Further Reading

进一步阅读

Skaffman did a great job on explaining ApplicationContexthierarchies in this answer, which is highly recommended. Also, you can read Spring Documentation.

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

回答by shazin

Root Config Classes are actually used to Create Beans which are Application Specific and which needs to be available for Filters (As Filters are not part of Servlet).

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

Servlet Config Classes are actually used to Create Beans which are DispatcherServlet specific such as ViewResolvers, ArgumentResolvers, Interceptor, etc.

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

Root Config Classes will be loaded first and then Servlet Config Classes will be loaded.

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

Root Config Classes will be the Parent Context and it will create a ApplicationContextinstace. Where as Servlet Config Classes will be the Child Context of the Parent Context and it will create a WebApplicationContextinstance.

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

In your ConServletConfiguration, You don't need to specify the @EnableWebMvcas well the InternalResourceViewResolverbean as they are only required at the WebConfig.

在你的ConServlet配置,你并不需要指定@EnableWebMvc为好InternalResourceViewResolver,因为它们是在只需豆WebConfig