java - spring 4 hibernate 4 example
ContextLoaderListener o no? (3)
En su caso, no, no hay razón para mantener ContextLoaderListener
y applicationContext.xml
. Si su aplicación funciona bien solo con el contexto del servlet, eso se mantiene, es más simple.
Sí, el patrón generalmente recomendado es mantener cosas que no son web en el contexto de nivel de aplicación web, pero no es más que una convención débil.
Las únicas razones convincentes para usar el contexto de nivel de aplicación web son:
- Si tiene varios
DispatcherServlet
que necesitan compartir servicios - Si tiene servlets heredados / no Spring que necesitan acceso a los servicios de Spring-wired
- Si tiene filtros de servlet que se enganchan en el contexto del nivel de aplicación web (por ejemplo,
DelegatingFilterProxy
Spring Security,OpenEntityManagerInViewFilter
, etc.)
Ninguno de estos se aplica a usted, por lo que la complejidad adicional no está justificada.
Solo tenga cuidado al agregar tareas en segundo plano al contexto del servlet, como tareas programadas, conexiones JMS, etc. Si olvida agregar <load-on-startup>
a su web.xml
, estas tareas no se iniciarán hasta la primera acceso del servlet.
Una aplicación web estándar de primavera (creada por Roo o la plantilla "Spring MVC Project") crea un web.xml con ContextLoaderListener
y DispatcherServlet
. ¿Por qué no solo usan el DispatcherServlet
y lo hacen para cargar la configuración completa?
Entiendo que el ContextLoaderListener se debe usar para cargar cosas que no son relevantes para la web y el DispatcherServlet se usa para cargar las cosas relevantes de la web (Controladores, ...). Y este resultado en dos contextos: un contexto padre y otro hijo.
Fondo:
Lo estaba 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 estoy enfrentando un problema con los eventos de ambos contextos .
- Sin embargo, esto hace que reconsidere este patrón de dos contextos, y me pregunto: ¿por qué debería meterme en este problema, por qué no cargar todos los archivos de configuración de primavera con un ContextLoaderListener
DispatcherServlet
y eliminar ContextLoaderListener
completo el ContextLoaderListener
? (Todavía tendré diferentes archivos de configuración, pero solo un contexto).
¿Hay alguna razón para no eliminar el ContextLoaderListener
?
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 archivos
applicationContext.xml
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>
También puede configurar el contexto de la aplicación al revés. Por ejemplo, para hacer que OpenEntityManagerInViewFilter funcione. Configure el 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.