getServletConfigClasses() vs. getRootConfigClasses() beim Erweitern von AbstractAnnotationConfigDispatcherServletInitializer

Lesezeit: 5 Minuten

Benutzer-Avatar
Plain_Dude_Sleeping_Alone

Was ist der Unterschied zwischen getServletConfigClasses() vs getRootConfigClasses() beim Verlängern AbstractAnnotationConfigDispatcherServletInitializer. Ich habe seit heute Morgen viele Quellen gelesen, aber ich habe noch kein klares Verständnis für die Unterschiede bekommen:

Bitte sehen Sie sich diese beiden Konfigurationen an:

1).

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

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

Das ConServlet.class bezieht sich auf

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

das WebConfig.class bezieht sich auf

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

Ich sehe beides ConServlet & WebConfig (mehr oder weniger) die gleichen Dinge tun wie das Initialisieren von view :

Aber wieso :

  • ConServlet wird zurückgegeben getRootConfigClasses()
  • während WebConfig wird zurückgegeben getServletConfigClasses()

Ich habe die Dokumentation gelesen

beide getRootConfigClasses() & getServletConfigClasses() ist für

Geben Sie @Configuration- und/oder @Component-Klassen an, die bereitgestellt werden sollen.. (ihre Unterschiede)

  • den Root-Anwendungskontext zum getRootConfigClasses()
  • der Dispatcher-Servlet-Anwendungskontext für getServletConfigClasses()

aber warum dann ConServlet & WebConfig Wenn ich die gleichen Dinge tue (wie die Initialisierung der Ansicht), bin ich vielleicht derjenige, der es missverstanden hat. Was eigentlich Root-Context und Dispatcher-Servlets (diese kenne ich) sind in der einfacher Begriff/Beispiel

Vielen Dank!

Benutzer-Avatar
Ali Deghani

Ein bisschen weiter ApplicationContext Hierarchien


Frühling ist ApplicationContext bietet die Möglichkeit, mehrere (hierarchische) Kontexte zu laden, sodass sich jeder auf eine bestimmte Ebene konzentrieren kann, z. B. die Webebene einer Anwendung oder Dienste der mittleren Ebene.

Eines der kanonischen Beispiele für die Verwendung von hierarchical ApplicationContext ist, wenn wir mehrere haben DispatcherServlets in einer Webanwendung und wir werden einige der gängigen Beans teilen, wie z datasources zwischen ihnen. Auf diese Weise können wir eine Wurzel definieren ApplicationContext die alle gängigen Bohnen und mehrere enthalten WebApplicationContexts, die die Common Beans aus dem Root-Kontext erben.

Im Web-MVC-Framework jede DispatcherServlet hat sein eigenes WebApplicationContextdie alle bereits im Stamm definierten Beans erbt WebApplicationContext. Diese geerbten Beans können im servletspezifischen Geltungsbereich überschrieben werden, und Sie können neue bereichsspezifische Beans lokal für einen gegebenen definieren Servlet Beispiel.

Typische Kontexthierarchie in Spring Web MVC
Typische Kontexthierarchie in Spring Web MVC (Spring Documentation)

Wenn Sie in einem Single leben DispatherServlet world ist es auch möglich, nur einen Root-Kontext für dieses Szenario zu haben:

Geben Sie hier die Bildbeschreibung ein
Einzelner Stammkontext in Spring Web MVC (Spring-Dokumentation)

Reden ist billig. Zeig mir den Code!


Angenommen, wir entwickeln eine Webanwendung und verwenden Spring MVC, Spring Security und Spring Data JPA. Für dieses einfache Szenario hätten wir mindestens drei verschiedene Konfigurationsdateien. EIN WebConfig das alle unsere webbezogenen Konfigurationen enthält, wie z ViewResolvers, Controllers, ArgumentResolvers usw. Etwas wie folgt:

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

Hier definiere ich a ViewResolver um meine einfachen alten JSPs zu lösen, schlechte Lebensentscheidungen im Grunde. Wir bräuchten eine RepositoryConfigdie alle Datenzugriffsmöglichkeiten wie enthält DataSource, EntityManagerFactory, TransactionManagerusw. Es wäre wahrscheinlich wie folgt:

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

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

Und ein SecurityConfig die alle sicherheitsrelevanten Sachen enthält!

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

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

Um all dies zusammenzukleben, haben wir zwei Möglichkeiten. Zunächst können wir eine typische Hierarchie definieren ApplicationContextbeim Hinzufügen RepositoryConfig und SecurityConfig im Stammkontext und WebConfig in ihrem untergeordneten Kontext:

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

Da wir eine Single haben DispatcherServlet Hier können wir die hinzufügen WebConfig in den Root-Kontext und leeren Sie den Servlet-Kontext:

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

Weiterführende Lektüre


Skaffman hat großartige Arbeit geleistet, um zu erklären ApplicationContext Hierarchien in dieser Antwort, was sehr zu empfehlen ist. Außerdem kann man lesen Frühlingsdokumentation.

  • Ok, ich werde versuchen, Ihre Antwort (ab morgen) für die nächsten 2 Tage zu studieren / aufzunehmen, danke, jetzt werde ich sie positiv bewerten.

    – Plain_Dude_Sleeping_Alone

    16. Februar 2016 um 20:20 Uhr


  • Eine tolle Antwort. Eine Sache, die es wert ist, darauf hinzuweisen, ist das mit @ComponentScan ist, dass es auch abholen wird @Configuration Klassen, da sie auch Komponenten sind, die dazu führen können, dass Beans in beiden Kontexten zweimal geladen werden. Aus diesem Grund schließe ich das immer explizit aus @Configuration aus @ComponentScanwas eine kontrolliertere Konfiguration ermöglicht.

    – Brett Ryan

    14. August 2016 um 22:46 Uhr

Root-Konfigurationsklassen werden tatsächlich verwendet, um Beans zu erstellen, die anwendungsspezifisch sind und die für Filter verfügbar sein müssen (da Filter nicht Teil des Servlets sind).

Servlet-Konfigurationsklassen werden tatsächlich zum Erstellen von DispatcherServlet-spezifischen Beans wie ViewResolvers, ArgumentResolvers, Interceptor usw. verwendet.

Root-Konfigurationsklassen werden zuerst geladen und dann werden Servlet-Konfigurationsklassen geladen.

Root-Konfigurationsklassen sind der übergeordnete Kontext und erstellen eine ApplicationContext z.B. Wobei Servlet-Konfigurationsklassen der untergeordnete Kontext des übergeordneten Kontexts sind und eine erstellen WebApplicationContext Beispiel.

In deiner ConServlet Konfiguration, Sie müssen die nicht angeben @EnableWebMvc ebenso die InternalResourceViewResolver Bohne, da sie nur bei der benötigt werden WebConfig.

  • Helo, Sir, danke, aber könnten Sie mehr Details für die angeben? Root-Konfig Fall, wie ein kurzer Ausschnitt (muss nicht sehr detailliert sein).

    – Plain_Dude_Sleeping_Alone

    16. Februar 2016 um 8:59 Uhr


1043450cookie-checkgetServletConfigClasses() vs. getRootConfigClasses() beim Erweitern von AbstractAnnotationConfigDispatcherServletInitializer

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy