Qual é a diferença entre getServletConfigClasses()
vs getRootConfigClasses()
ao estender AbstractAnnotationConfigDispatcherServletInitializer
. Eu tenho lido muitas fonts desde esta manhã, mas ainda não entendi claramente as diferenças:
Por favor, olhe para estas duas configurações:
1).
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { return new Class[] { ConServlet.class }; } @Override protected Class[] getServletConfigClasses() { return null; } .... .... }
O ConServlet.class
está se referindo a
@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 }; } ..... }
o WebConfig.class está se referindo a
@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; } }
Eu vejo tanto ConServlet e WebConfig (mais ou menos) fazendo as mesmas coisas como inicializando a visão:
Mas por que :
getRootConfigClasses()
getServletConfigClasses()
Eu li a documentação
getRootConfigClasses () e getServletConfigClasses () é para
Especifique as classs @Configuration e / ou @Component a serem fornecidas para .. (suas diferenças)
getRootConfigClasses()
getServletConfigClasses()
mas por que, então, o ConServlet & WebConfig fazendo as mesmas coisas (como a visualização de boot), talvez eu tenha entendido errado. O que são realmente os servlets de contexto e dispatcher de raiz (eu conheço este) no termo / exemplo simples
Obrigado!
ApplicationContext
Spring ApplicationContext
fornece a capacidade de carregar vários contextos (hierárquicos), permitindo que cada um seja focado em uma camada específica, como a camada web de um aplicativo ou serviços de camada intermediária.
Um dos exemplos canônicos do uso de ApplicationContext
hierárquico é quando temos vários DispatcherServlet
s em um aplicativo da Web e vamos compartilhar alguns dos beans comuns, como datasources
entre eles. Dessa forma, podemos definir um ApplicationContext
raiz que contém todos os beans comuns e vários WebApplicationContext
s que herdam os beans comuns do contexto raiz.
Na estrutura Web MVC, cada DispatcherServlet
possui seu próprio WebApplicationContext
, que herda todos os beans já definidos no WebApplicationContext
raiz. Esses beans herdados podem ser substituídos no escopo específico do servlet, e você pode definir novos beans específicos do escopo para uma determinada instância do Servlet
.
Hierarquia de contexto típica no Spring Web MVC (Documentação Spring)
Se você está vivendo em um único mundo DispatherServlet
, também é possível ter apenas um contexto raiz para este cenário:
Contexto raiz única no Spring Web MVC (Documentação Spring)
Suponha que vamos desenvolver uma aplicação web e vamos usar o Spring MVC, o Spring Security e o Spring Data JPA. Para este cenário simples, teríamos pelo menos três arquivos de configuração diferentes. Um WebConfig
que contém todas as nossas configurações relacionadas à web, como ViewResolver
s, Controller
s, ArgumentResolver
s, etc. Algo como seguir:
@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); } }
Aqui estou definindo um ViewResolver
para resolver meus simples jsps antigos, decisões ruins sobre a vida, basicamente. Nós precisaríamos de um RepositoryConfig
, que contém todos os resources de access a dados, como DataSource
, EntityManagerFactory
, TransactionManager
, etc. Provavelmente seria como seguir:
@Configuration @EnableTransactionManagement @EnableJpaRepositories(basePackages = "com.so.repository") public class RepositoryConfig { @Bean public DataSource dataSource() { ... } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... } @Bean public PlatformTransactionManager transactionManager() { ... } }
E um SecurityConfig
que contém todo o material relacionado à segurança!
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... } @Override protected void configure(HttpSecurity http) throws Exception { ... } }
Para colar tudo isso juntos, temos duas opções. Primeiro, podemos definir um ApplicationContext
hierárquico típico, adicionando RepositoryConfig
e SecurityConfig
no contexto raiz e WebConfig
em seu contexto filho:
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[] { "/" }; } }
Como temos um único DispatcherServlet
aqui, podemos adicionar o WebConfig
ao contexto raiz e tornar o contexto do servlet vazio:
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 fez um ótimo trabalho explicando hierarquias ApplicationContext
nesta resposta , o que é altamente recomendado. Além disso, você pode ler a documentação do Spring .
As classs de configuração raiz são realmente usadas para criar beans que são específicos do aplicativo e que precisam estar disponíveis para filtros (como os filtros não fazem parte do servlet).
As classs de configuração do servlet são realmente usadas para criar beans que são específicos do DispatcherServlet, como ViewResolvers, ArgumentResolvers, Interceptor, etc.
As Classes de Configuração Raiz serão carregadas primeiro e, em seguida, as Classes de Configuração do Servlet serão carregadas.
As Classes de Configuração Raiz serão o Contexto Pai e criarão uma instância do ApplicationContext
. Onde, como Classes de Configuração de Servlet, será o Contexto Filho do Contexto Pai e ele criará uma instância de WebApplicationContext
.
Na sua configuração ConServlet
, você não precisa especificar o @EnableWebMvc
, assim como o bean InternalResourceViewResolver
pois eles são necessários apenas no WebConfig
.