web-dev-qa-db-ja.com

AbstractAnnotationConfigDispatcherServletInitializerを拡張する場合のgetServletConfigClasses()とgetRootConfigClasses()

getServletConfigClasses() vs getRootConfigClasses()を拡張するときの違いは何ですかAbstractAnnotationConfigDispatcherServletInitializer。私は今朝から多くの情報源を読んでいますが、違いについてはまだ明確な理解が得られていません。

次の2つの構成をご覧ください。

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(多かれ少なかれ)ビューの初期化のような同じことを行う両方を見ます:

しかし、なぜ :

  • ConServletgetRootConfigClasses()で返されます
  • while WebConfiggetServletConfigClasses()で返されます

ドキュメントを読みます

両方getRootConfigClasses()getServletConfigClasses()

提供する@Configurationクラスまたは@Componentクラス、あるいはその両方を指定します(それらの違い)

  • ルートアプリケーションコンテキスト for getRootConfigClasses()
  • ディスパッチャサーブレットアプリケーションコンテキストgetServletConfigClasses()

しかし、なぜConServletWebConfig同じこと(ビューの初期化など)を行うと、多分私はそれを誤解しているかもしれません。 単純な用語/例の実際のルートコンテキストおよびディスパッチャサーブレット(これは知っています)

ありがとうございました!

ApplicationContext階層のビット


SpringのApplicationContextは、複数の(階層)コンテキストをロードする機能を提供し、各コンテキストがアプリケーションのWebレイヤーや中間層サービスなどの特定の1つのレイヤーに集中できるようにします。

階層ApplicationContextを使用する標準的な例の1つは、Webアプリケーションに複数のDispatcherServletがあり、datasourcesなどの一般的なBeanのいくつかを共有する場合です。それら。このようにして、すべての共通Beanを含むルートApplicationContextと、ルートコンテキストから共通Beanを継承する複数のWebApplicationContextsを定義できます。

Web MVCフレームワークでは、各DispatcherServletには独自のWebApplicationContextがあり、ルートWebApplicationContextで既に定義されているすべてのBeanを継承します。これらの継承されたBeanは、サーブレット固有のスコープでオーバーライドできます。また、特定のServletインスタンスに対してローカルな新しいスコープ固有のBeanを定義できます。

Typical context hierarchy in Spring Web MVC
Spring Web MVCの典型的なコンテキスト階層(Springドキュメント)

単一のDispatherServletワールドに住んでいる場合、このシナリオのルートコンテキストを1つだけ持つこともできます。

enter image description here
Spring Web MVCのシングルルートコンテキスト(Springドキュメント)

トークは安いです、コードを見せてください!


Webアプリケーションを開発していて、Spring MVC、Spring Security、Spring Data JPAを使用するとします。この単純なシナリオでは、少なくとも3つの異なる構成ファイルがあります。 WebConfigs、ViewResolvers、Controllersなど、Web関連のすべての構成を含む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);
    }
}

ここでは、基本的にViewResolverを定義して、単純な古いjsp、貧弱な人生決定を解決しています。 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 { ... }
}

これらすべてを一緒に接着するには、2つのオプションがあります。まず、ルートコンテキストにApplicationContextRepositoryConfigを追加し、それらの子コンテキストに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があるので、WebConfigをルートコンテキストに追加して、サーブレットコンテキストを空にすることができます。

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は、この answerApplicationContext階層を説明する上で素晴らしい仕事をしました。これは強くお勧めします。また、 Spring Documentation を読むことができます。

92
Ali Dehghani

ルート構成クラスは、実際には、アプリケーション固有であり、フィルターに使用できる必要があるBeanを作成するために使用されます(フィルターはサーブレットの一部ではないため)。

Servlet Configクラスは、ViewResolvers、ArgumentResolvers、InterceptorなどのDispatcherServlet固有のBeanを作成するために実際に使用されます。

ルート構成クラスが最初にロードされ、次にサーブレット構成クラスがロードされます。

ルート構成クラスは親コンテキストになり、ApplicationContextインスタンスを作成します。 Servlet Config Classesが親コンテキストの子コンテキストであり、WebApplicationContextインスタンスを作成する場所。

ConServlet構成では、InternalResourceViewResolverでのみ必要であるため、@EnableWebMvcおよびWebConfig Beanを指定する必要はありません。

4
shazin