getServletConfigClasses() против getRootConfigClasses() при расширении AbstractAnnotationConfigDispatcherServletInitializer
В чем разница между getServletConfigClasses()
против 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;
}
}
Я вижу, что и ConServlet, и WebConfig (более или менее) выполняют одни и те же действия, например инициализация представления:
Но почему:
- ConServlet возвращается в
getRootConfigClasses()
- в то время как WebConfig возвращается в
getServletConfigClasses()
Я читаю документацию
оба getRootConfigClasses() и getServletConfigClasses() предназначены для
Укажите классы @Configuration и / или @Component, которые будут предоставлены.. (их различия)
- корневой контекст приложения для
getRootConfigClasses()
- контекст приложения диспетчера сервлетов для
getServletConfigClasses()
но почему тогда ConServlet & WebConfig делают то же самое (например, инициализирующий просмотр), может быть, я это неправильно понял. Что такое на самом деле корневой контекст и диспетчерские сервлеты (я знаю это) в простом термине / примере
Спасибо!
2 ответа
Немного на ApplicationContext
Иерархии
Спринга ApplicationContext
обеспечивает возможность загрузки нескольких (иерархических) контекстов, позволяя каждому из них быть сосредоточенным на одном конкретном уровне, таком как веб-уровень приложения или сервисы среднего уровня.
Один из канонических примеров использования иерархического ApplicationContext
когда у нас есть несколько DispatcherServlet
S в веб-приложении, и мы собираемся поделиться некоторыми из распространенных компонентов, таких как datasources
между ними. Таким образом, мы можем определить корень ApplicationContext
которые содержат все общие бобы и несколько WebApplicationContext
s, которые наследуют общие бины из корневого контекста.
В рамках Web MVC каждый DispatcherServlet
имеет свой WebApplicationContext
, который наследует все бины, уже определенные в корне WebApplicationContext
, Эти унаследованные bean-компоненты могут быть переопределены в области, зависящей от сервлета, и вы можете определить новые bean-компоненты, зависящие от области, локально для данной области. Servlet
пример.
Типичная контекстная иерархия в Spring Web MVC (Spring Documentation)
Если вы живете в одиночном DispatherServlet
В этом сценарии также возможно иметь только один корневой контекст:
Единый корневой контекст в Spring Web MVC (Spring Documentation)
Обсуждение дешево, покажи мне код!
Предположим, мы разрабатываем веб-приложение и собираемся использовать Spring MVC, Spring Security и Spring Data JPA. Для этого простого сценария у нас было бы как минимум три разных конфигурационных файла. WebConfig
который содержит все наши веб-связанные конфигурации, такие как ViewResolver
s, Controller
s, 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
чтобы решить мои старые добрые jsps, плохие жизненные решения, в основном. Нам понадобится RepositoryConfig
, который содержит все средства доступа к данным, такие как DataSource
, EntityManagerFactory
, 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 { ... }
}
Для склейки всего этого у нас есть два варианта. Во-первых, мы можем определить типичную иерархическую ApplicationContext
, добавляя RepositoryConfig
а также 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[] { "/" };
}
}
Дальнейшее чтение
Скаффман проделал большую работу по объяснению ApplicationContext
иерархии в этом ответе, что настоятельно рекомендуется. Также вы можете прочитать Spring Documentation.
Корневые классы конфигурации фактически используются для создания bean-компонентов, которые являются специфичными для приложения и которые должны быть доступны для фильтров (поскольку фильтры не являются частью сервлета).
Классы конфигурации сервлетов фактически используются для создания bean-компонентов, специфичных для DispatcherServlet, таких как ViewResolvers, ArgumentResolvers, Interceptor и т. Д.
Сначала будут загружены Root Config Classes, а затем будут загружены Servlet Config Classes.
Корневые классы конфигурации будут родительским контекстом и создадут ApplicationContext
instace. Где в качестве классов конфигурации сервлета будет дочерний контекст родительского контекста, и он создаст WebApplicationContext
пример.
В вашем ConServlet
Конфигурация, вам не нужно указывать @EnableWebMvc
а также InternalResourceViewResolver
боб, поскольку они требуются только на WebConfig
,