ContextLoaderListener o no?
Una aplicación web Spring estándar (creada por Roo o plantilla "Spring MVC Project") crea un web.xml con ContextLoaderListener
y DispatcherServlet
. ¿Por qué no solo usan DispatcherServlet
y cargan la configuración completa?
Entiendo que ContextLoaderListener debe usarse para cargar cosas que no son relevantes para la web y DispatcherServlet se usa para cargar cosas relevantes para la web (Controladores,...). Y esto resulta en dos contextos: un contexto padre y un contexto hijo.
Fondo:
Lo estuve haciendo de esta manera estándar durante varios años.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Handles Spring requests -->
<servlet>
<servlet-name>roo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Esto a menudo causaba problemas con los dos contextos y las dependencias entre ellos. En el pasado siempre pude encontrar una solución y tengo la fuerte sensación de que esto hace que la estructura/arquitectura del software sea siempre mejor. Pero ahora me enfrento a un problema con los acontecimientos de ambos contextos .
- Sin embargo, esto me hace reconsiderar estos dos patrones de contexto y me pregunto: ¿por qué debería meterme en este problema? ¿Por qué no cargar todos los archivos de configuración de Spring con uno DispatcherServlet
y eliminarlo ContextLoaderListener
por completo? (Aún tendré diferentes archivos de configuración, pero solo un contexto).
¿Hay alguna razón para no eliminar el ContextLoaderListener
?
En su caso, no, no hay razón para conservar ContextLoaderListener
y applicationContext.xml
. Si su aplicación funciona bien solo con el contexto del servlet, siga con eso, es más simple.
Sí, el patrón generalmente recomendado es mantener el material que no es web en el contexto del nivel de la aplicación web, pero no es más que una convención débil.
Las únicas razones convincentes para utilizar el contexto a nivel de aplicación web son:
- Si tiene varios
DispatcherServlet
que necesitan compartir servicios - Si tiene servlets heredados/que no son de Spring y necesitan acceso a servicios conectados a Spring
- Si tiene filtros de servlet que se conectan al contexto de nivel de aplicación web (por ejemplo, Spring Security
DelegatingFilterProxy
,OpenEntityManagerInViewFilter
etc.)
Ninguno de estos se aplica a usted, por lo que la complejidad adicional no se justifica.
Solo tenga cuidado al agregar tareas en segundo plano al contexto del servlet, como tareas programadas, conexiones JMS, etc. Si olvida agregarlas <load-on-startup>
a su archivo web.xml
, estas tareas no se iniciarán hasta el primer acceso al servlet.
También puedes configurar el contexto de la aplicación al revés. Por ejemplo, para que OpenEntityManagerInViewFilter funcione. Configure ContextLoaderListener y luego configure su DispatcherServlet con:
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
Solo asegúrese de que el valor del parámetro contextConfigLocation esté vacío.
Quiero compartir lo que hice en mi aplicación Spring-MVC:
En el
we-mvc-config.xml
agregué solo las clases anotadas con @Controller:<context:component-scan base-package="com.shunra.vcat"> <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> </context:component-scan>
En los
applicationContext.xml
archivos agregué todo el resto:<context:component-scan base-package="com.shunra.vcat"> <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> </context:component-scan>