getServletConfigClasses () vs getRootConfigClasses () lors de l'extension AbstractAnnotationConfigDispatcherservletinitializer

Quelle est la différence entre getServletConfigClasses() et getRootConfigClasses() lors de l'extension AbstractAnnotationConfigDispatcherServletInitializer. J'ai lu beaucoup de sources depuis ce matin mais je n'ai pas encore compris clairement les différences:

s'il vous Plaît un coup d'oeil à ces deux configurations :

1).

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

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

ConServlet.class fait référence à

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

la WebConfig.classe fait référence à

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

je vois deux ConServlet& WebConfig (plus ou moins) faisant les mêmes choses comme la vue initialisante:

Mais pourquoi :

  • ConServlet est retourné dans getRootConfigClasses()
  • WebConfig est retourné dans getServletConfigClasses()

j'ai lu la documentation

getRootConfigClasses ()& getServletConfigClasses ()

Spécifier @Configuration et / ou @classes de composants à fournir.. (leurs différences )

  • le contexte de l'application racinegetRootConfigClasses()
  • le répartiteur servlet contexte de l'application pourgetServletConfigClasses()

mais pourquoi alors ConServlet& WebConfig faire les mêmes choses (comme initialiser la vue), peut-être que c'est moi qui l'ai mal compris. Ce qui est en fait le contexte racine et les servlets de répartiteur (je connais celui-ci) dans le terme simple/exemple

Merci!

38
demandé sur Ali Dehghani 2016-02-07 23:32:38

2 réponses

un peu sur ApplicationContext Hiérarchies

Ressort ApplicationContext fournit la possibilité de charger plusieurs contextes (hiérarchiques), permettant à chacun d'être concentré sur une couche particulière, telle que la couche web d'une application ou des services de niveau intermédiaire.

un des exemples canoniques d'utilisation de ApplicationContext c'est quand nous avons plusieurs DispatcherServlet s dans une application web et nous allons partager certains des haricots communs tels que datasources entre eux. De cette façon, nous pouvons définir une racine ApplicationContext qui contiennent tous les haricots communs et plusieurs WebApplicationContext s qui héritent les haricots communs du contexte de la racine.

Dans le Web framework MVC, chaque DispatcherServlet a son propre WebApplicationContext, qui hérite de tous les grains déjà définis dans la racine WebApplicationContext. Ces fèves héritées peuvent être supplantées dans la portée spécifique à une portion, et vous pouvez définir de nouvelles fèves spécifiques à une portion donnéeServlet instance.

Typical context hierarchy in Spring Web MVC

Typique contexte de hiérarchie dans Web Spring MVC (Printemps Documentation)

si vous vivez seul DispatherServlet monde, il est également possible d'avoir un seul contexte de la racine pour ce scénario:

enter image description here

contexte de racine simple dans le Web de printemps MVC (printemps La Documentation)

parler c'est pas cher, Montrez-moi le code!

supposons que nous développions une application web et que nous utilisions Spring MVC, Spring Security et Spring Data JPA. Pour ce scénario simple, nous aurions au moins trois fichiers de configuration différents. WebConfig qui contient toutes nos configurations liées au web, comme ViewResolver s,Controller s,ArgumentResolver s, etc. Quelque chose comme suit:

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

Ici je suis la définition d'un ViewResolver pour résoudre mes vieux jsps, de mauvaises décisions de vie, en gros. Nous aurions besoin d'un RepositoryConfig, qui contient toutes les facilités d'accès aux données telles que DataSource,EntityManagerFactory,TransactionManager, etc. Il serait sans doute comme suit:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.so.repository")
public class RepositoryConfig {
    @Bean
    public DataSource dataSource() { ... }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... }

    @Bean
    public PlatformTransactionManager transactionManager() { ... }
}

Et SecurityConfig qui contient tous les trucs liés à la sécurité!

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }

    @Override
    protected void configure(HttpSecurity http) throws Exception { ... }
}

pour coller tout cela ensemble, nous avons deux options. Tout d'abord, on peut définir une typique hiérarchique ApplicationContext, en ajoutant RepositoryConfig et SecurityConfig dans le contexte de la racine et WebConfig dans le contexte de leur enfant:

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

Depuis que nous avons un seul DispatcherServlet ici, on peut ajouter le WebConfig au contexte root et vider le contexte 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[] { "/" };
    }
}

Autres Lectures

Skaffman a fait du bon travail en expliquant ApplicationContext hiérarchies dans ce réponse, ce qui est fortement recommandé. Aussi, vous pouvez lire Documentation De Printemps.

77
répondu Ali Dehghani 2017-05-23 12:26:24

les Classes de configuration racine sont en fait utilisées pour créer des fèves qui sont spécifiques à L'Application et qui doivent être disponibles pour les filtres (car les filtres ne font pas partie de Servlet).

les Classes de configuration des servlets sont en fait utilisées pour créer des fèves qui sont spécifiques aux répartiteurs comme ViewResolvers, ArgumentResolvers, Interceptor, etc.

les Classes de configuration racine seront chargées en premier et les classes de configuration Servlet seront ensuite chargées.

les Classes de configuration racine vont être le Parent Contexte et il va créer un ApplicationContext instace. Où as Servlet Config Classes sera le contexte enfant du contexte Parent et créera un WebApplicationContext instance.

Dans votre ConServlet Configuration, vous n'avez pas besoin de spécifier le @EnableWebMvc dans le InternalResourceViewResolver bean comme ils ne sont tenus à l' WebConfig.

4
répondu shazin 2016-02-16 08:46:54