Spring + Web MVC: dispatcher-servlet.xml vs. applicationContext.xml (más seguridad compartida)

¿Cuál es la forma correcta de usar los dos contextos: dispatcher-servlet.xml y applicationContext.xml ? ¿Qué va donde?

Quiero escribir una aplicación bastante típica implementada en un contenedor de servlets. Tiene algunos controladores con vistas JSP. También tiene una lógica no trivial en el back-end. ¿Realmente necesito ambos contextos? ¿Cómo es que están relacionados? ¿Cómo puedo decidir qué poner en qué?

Además, quiero usar Spring-security para mi aplicación. Es posible que desee utilizar sus características (como la seguridad declarativa con anotaciones) en los controladores web, así como en capas más profundas. ¿Cómo debo configurar la seguridad para que funcione en este caso? ¿Debería estar en uno de esos archivos (¿cuál?), O en ambos?

El archivo dispatcher-servlet.xml contiene toda su configuración para Spring MVC . Por lo tanto, en él encontrará frijoles como ViewHandlerResolvers , ConverterFactories , Interceptors , entre otros. Todos estos beans forman parte de Spring MVC que es un marco que estructura la forma en que manejas las solicitudes web, proporcionando funciones útiles como enlaces de datos, resolución de vistas y mapeo de solicitudes.

El application-context.xml se puede incluir opcionalmente cuando se usa Spring MVC o cualquier otro framework para ese asunto. Esto le da un contenedor que puede usarse para configurar otros tipos de granos de spring que brindan soporte para cosas como la persistencia de los datos. Básicamente, en este archivo de configuración es donde puedes obtener todos los otros beneficios que ofrece Spring.

Estos archivos de configuración están configurados en el archivo web.xml como se muestra:

Dispatcher Config

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

Configuración de la aplicación

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

Para configurar controladores, @Controller con @Controller luego incluya lo siguiente en el archivo dispatcher-context.xml :

   

Para agregar a la respuesta de Kevin, encuentro que en la práctica casi todas sus aplicaciones Spring MVC no triviales requerirán un contexto de aplicación (a diferencia de solo el contexto del servlet del despachador MVC de spring). Es en el contexto de la aplicación que debe configurar todas las inquietudes no relacionadas con la web, tales como:

  • Seguridad
  • Persistencia
  • Tareas progtwigdas
  • ¿Otros?

Para hacer esto un poco más concreto, aquí hay un ejemplo de la configuración de Spring que he usado al configurar una versión moderna (Spring versión 4.1.2) Spring MVC. Personalmente, prefiero seguir usando un archivo WEB-INF/web.xml , pero esa es realmente la única configuración xml a la vista.

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

Como puede ver, la configuración web es solo una pequeña parte de la configuración general de la aplicación web de spring. La mayoría de las aplicaciones web con las que he trabajado tienen muchas inquietudes que se encuentran fuera de la configuración del servlet del despachador que requieren un contexto de aplicación completamente desarrollado mediante el org.springframework.web.context.ContextLoaderListener en el 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