Spring + Web MVC: dispatcher-servlet.xml vs applicationContext.xml (plus sécurité partagée)

Quelle est la manière correcte d’utiliser les deux contextes: dispatcher-servlet.xml et applicationContext.xml ? Qu’est-ce qui se passe où?

Je veux écrire une application assez typique déployée dans un conteneur de servlets. Il a des contrôleurs avec des vues JSP. Il a également une logique non sortingviale en arrière. Ai-je vraiment besoin des deux contextes? Comment sont-ils liés les uns aux autres? Comment puis-je décider quoi mettre?

De plus, je souhaite utiliser la sécurité Spring pour mon application. Je peux vouloir utiliser ses fonctionnalités (comme la sécurité déclarative avec des annotations) dans les contrôleurs Web ainsi que dans les couches plus profondes. Comment configurer la sécurité pour fonctionner dans ce cas? Devrait-il être dans l’un de ces fichiers (qui?), Ou les deux?

Le fichier dispatcher-servlet.xml contient toute votre configuration pour Spring MVC . Vous y trouverez donc des beans tels que ViewHandlerResolvers , ConverterFactories , Interceptors , etc. Tous ces beans font partie de Spring MVC une structure qui structure la façon dont vous gérez les requêtes Web, en fournissant des fonctionnalités utiles telles que la liaison de données, la résolution des vues et le mappage des requêtes.

Le application-context.xml peut éventuellement être inclus lors de l’utilisation de Spring MVC ou de toute autre structure à cet égard. Cela vous donne un conteneur qui peut être utilisé pour configurer d’autres types de beans Spring qui prennent en charge des éléments tels que la persistance des données. Fondamentalement, dans ce fichier de configuration, vous trouverez toutes les autres offres de spring.

Ces fichiers de configuration sont configurés dans le fichier web.xml comme indiqué:

Configuration du répartiteur

  dispatcher org.springframework.web.servlet.DispatcherServlet  contextConfigLocation WEB-INF/spring/servlet-context.xml  1   dispatcher /  

Configuration de l’application

  contextConfigLocation /WEB-INF/spring/application-context.xml    org.springframework.web.context.ContextLoaderListener  

Pour configurer les contrôleurs, @Controller les avec @Controller puis incluez les éléments suivants dans le fichier dispatcher-context.xml :

   

Pour append à la réponse de Kevin, je trouve que dans la pratique, presque toutes vos applications non sortingviales de Spring MVC nécessiteront un contexte d’application (par opposition au seul contexte de servlet du répartiteur MVC de Spring). C’est dans le contexte de l’application que vous devez configurer toutes les préoccupations non liées au Web, telles que:

  • Sécurité
  • Persistance
  • Tâches planifiées
  • Autres?

Pour rendre cela plus concret, voici un exemple de la configuration Spring que j’ai utilisée lors de la configuration d’une application Spring MVC moderne (Spring version 4.1.2). Personnellement, je préfère encore utiliser un fichier WEB-INF/web.xml , mais c’est vraiment la seule configuration XML en vue.

WEB-INF / web.xml

    openEntityManagerInViewFilter org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter   springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy    springSecurityFilterChain /*   openEntityManagerInViewFilter /*   springMvc org.springframework.web.servlet.DispatcherServlet 1  contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext   contextConfigLocation com.company.config.WebConfig    contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext   contextConfigLocation com.company.config.AppConfig   org.springframework.web.context.ContextLoaderListener   springMvc /   30    *.jsp true    

WebConfig.java

 @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.company.controller") public class WebConfig { @Bean public InternalResourceViewResolver getInternalResourceViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; } } 

AppConfig.java

 @Configuration @ComponentScan(basePackages = "com.company") @Import(value = {SecurityConfig.class, PersistenceConfig.class, ScheduleConfig.class}) public class AppConfig { // application domain @Beans here... } 

Security.java

 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private LdapUserDetailsMapper ldapUserDetailsMapper; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/**/js/**").permitAll() .antMatchers("/**/images/**").permitAll() .antMatchers("/**").access("hasRole('ROLE_ADMIN')") .and().formLogin(); http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.ldapAuthentication() .userSearchBase("OU=App Users") .userSearchFilter("sAMAccountName={0}") .groupSearchBase("OU=Development") .groupSearchFilter("member={0}") .userDetailsContextMapper(ldapUserDetailsMapper) .contextSource(getLdapContextSource()); } private LdapContextSource getLdapContextSource() { LdapContextSource cs = new LdapContextSource(); cs.setUrl("ldaps://ldapServer:636"); cs.setBase("DC=COMPANY,DC=COM"); cs.setUserDn("CN=administrator,CN=Users,DC=COMPANY,DC=COM"); cs.setPassword("password"); cs.afterPropertiesSet(); return cs; } } 

PersistenceConfig.java

 @Configuration @EnableTransactionManagement @EnableJpaRepositories(transactionManagerRef = "getTransactionManager", entityManagerFactoryRef = "getEntityManagerFactory", basePackages = "com.company") public class PersistenceConfig { @Bean public LocalContainerEntityManagerFactoryBean getEntityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean(); lef.setDataSource(dataSource); lef.setJpaVendorAdapter(getHibernateJpaVendorAdapter()); lef.setPackagesToScan("com.company"); return lef; } private HibernateJpaVendorAdapter getHibernateJpaVendorAdapter() { HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter(); hibernateJpaVendorAdapter.setDatabase(Database.ORACLE); hibernateJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect"); hibernateJpaVendorAdapter.setShowSql(false); hibernateJpaVendorAdapter.setGenerateDdl(false); return hibernateJpaVendorAdapter; } @Bean public JndiObjectFactoryBean getDataSource() { JndiObjectFactoryBean jndiFactoryBean = new JndiObjectFactoryBean(); jndiFactoryBean.setJndiName("java:comp/env/jdbc/AppDS"); return jndiFactoryBean; } @Bean public JpaTransactionManager getTransactionManager(DataSource dataSource) { JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(); jpaTransactionManager.setEntityManagerFactory(getEntityManagerFactory(dataSource).getObject()); jpaTransactionManager.setDataSource(dataSource); return jpaTransactionManager; } } 

ScheduleConfig.java

 @Configuration @EnableScheduling public class ScheduleConfig { @Autowired private EmployeeSynchronizer employeeSynchronizer; // cron pattern: sec, min, hr, day-of-month, month, day-of-week, year (optional) @Scheduled(cron="0 0 0 * * *") public void employeeSync() { employeeSynchronizer.syncEmployees(); } } 

Comme vous pouvez le constater, la configuration Web ne représente qu’une petite partie de la configuration globale de l’application Web Spring. La plupart des applications Web avec lesquelles j’ai travaillé ont de nombreuses préoccupations en dehors de la configuration du servlet du répartiteur, qui nécessitent un contexte d’application complet amorcé via org.springframework.web.context.ContextLoaderListener dans le org.springframework.web.context.ContextLoaderListener web.xml .

        /WEB-INF/pages/   .jsp    
           /WEB-INF/pages/   .jsp   

             /WEB-INF/pages/   .jsp    
   TestPOC  mvc-dispatcher org.springframework.web.servlet.DispatcherServlet 1   mvc-dispatcher /   contextConfigLocation /WEB-INF/mvc-dispatcher-servlet.xml   index.jsp