Diferencia entre applicationContext.xml y spring-servlet.xml en Spring Framework

373
  • ¿Están applicationContext.xmly están spring-servlet.xmlrelacionados de alguna manera en Spring Framework?
  • ¿Los archivos de propiedades declarados en applicationContext.xmlestarán disponibles para DispatcherServlet?
  • En una nota relacionada, ¿por qué necesito un *-servlet.xml? ¿Por qué applicationContext.xmlsolo es insuficiente?
usuario448070
fuente
1
Mira esto también. stackoverflow.com/questions/11708967/…
Sanghyun Lee

Respuestas:

430

Spring le permite definir múltiples contextos en una jerarquía padre-hijo.

El applicationContext.xmldefine los beans para el "contexto de la aplicación web raíz", es decir, el contexto asociado con la aplicación web.

El spring-servlet.xml(o como se llame) define los beans para el contexto de la aplicación de un servlet. Puede haber muchos de estos en una aplicación web, uno por servlet Spring (por ejemplo, spring1-servlet.xmlpara servlet spring1, spring2-servlet.xmlpara servlet spring2).

Los frijoles en spring-servlet.xmlpueden hacer referencia a los frijoles applicationContext.xml, pero no al revés.

Todos los controladores Spring MVC deben ir en el spring-servlet.xmlcontexto.

En la mayoría de los casos simples, el applicationContext.xmlcontexto es innecesario. Generalmente se usa para contener beans que se comparten entre todos los servlets en una aplicación web. Si solo tiene un servlet, entonces no tiene mucho sentido, a menos que tenga un uso específico para él.

skaffman
fuente
30
¿Por qué tendrías múltiples servlets de resorte?
NimChimpsky
55
respuesta poderosa y potente (debido a la brevedad)
anfibio
35
@NimChimpsky a veces es útil separar partes de su aplicación que de otro modo podrían entrar en conflicto en el mismo contexto. Como ejemplo, puede tener servicios ReST y vistas estándar, luego puede tener diferentes resoluciones de resolución o problemas de seguridad para los servicios en cuanto a las vistas.
Brett Ryan
12
¡La gente debería ver esta respuesta antes de leer la documentación y desarrollar aplicaciones! En casos normales, no es necesario tener ContextLoaderListener y contextConfigLocation, ¡solo DispatcherServlet!
ruruskyi
24
En muchos tutoriales contextConfigLocation contiene dispatcher-servlet.xml y DispatcherServlet. ¡Esto hace que los frijoles se inicialicen dos veces!
ruruskyi
106

escenario 1

En la aplicación cliente (la aplicación no es una aplicación web, por ejemplo, puede ser una aplicación swing)

private static ApplicationContext context = new  ClassPathXmlApplicationContext("test-client.xml");

context.getBean(name);

No necesita web.xml . ApplicationContext como contenedor para obtener el servicio bean. No es necesario el contenedor del servidor web. En test-client.xml puede haber Bean simple sin control remoto , Bean con control remoto .

Conclusión : en el Escenario 1 applicationContext y DispatcherServletno están relacionados.

Escenario 2

En una aplicación de servidor (aplicación implementada en el servidor, por ejemplo, Tomcat). Servicio accedido a través de comunicación remota desde el programa cliente (por ejemplo, la aplicación Swing)

Definir escucha en web.xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

En el inicio del servidor, se crean ContextLoaderListenerinstancias de beans definidos en applicationContext.xml .

Suponiendo que haya definido lo siguiente en applicationContext.xml :

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

Los beans se instancian de los cuatro archivos de configuración test1.xml , test2.xml , test3.xml , test4.xml .

Conclusión : en el Escenario 2 applicationContext y DispatcherServletno están relacionados.

Escenario 3

En una aplicación web con Spring MVC.

En web.xml define:

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

Cuando se inicia Tomcat, se crean instancias de beans definidos en springweb-servlet.xml . DispatcherServletse extiende FrameworkServlet. En el FrameworkServletfrijol se produce una instanciación para la primavera. En nuestro caso springweb es FrameworkServlet.

Conclusión : en el escenario 3 applicationContext yDispatcherServlet no están relacionados.

Escenario 4

En aplicación web con Spring MVC. springweb-servlet.xml para servlet y applicationContext.xml para acceder al servicio comercial dentro del programa del servidor o para acceder al servicio DB en otro programa de servidor.

En web.xml se definen los siguientes:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

Al inicio del servidor, ContextLoaderListenerinstancia los beans definidos en applicationContext.xml ; asumiendo que ha declarado aquí:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

Todos los beans se instancian de los cuatro test1.xml , test2.xml , test3.xml , test4.xml . Después de completar la creación de instancias de bean definida en applicationContext.xml , se crean instancias de beans definidos en springweb-servlet.xml .

Entonces, el orden de creación de instancias es: la raíz (contexto de la aplicación), luego FrameworkServlet.

Ahora debe quedar claro por qué son importantes en qué escenario.

abishkar bhattarai
fuente
10
+1. Muy bien. Estaba buscando este tipo de comparación, pero nunca la encontré.
Ninad Pingale
@abishkar bhattarai muy bien, mi pregunta es: entonces, ¿qué sucede si se usa la anotación @ Component y @ Value para crear un bean cuando "Escenario 4"
Lawrence
springweb DispatcherServletno se llamará si la url no termina con .action?
Asif Mushtaq
@lawrence Aún tendrá que especificar la ruta de clase en springweb-servlet.xml para que Spring pueda encontrar ese componente en su escaneo.
Veritas
54

Un punto más que quiero agregar. En spring-servlet.xmlincluimos escaneo de componentes para el paquete del controlador. En el siguiente ejemplo incluimos anotaciones de filtro para el paquete del controlador.

<!-- Scans for annotated @Controllers in the classpath -->
<context:component-scan base-package="org.test.web" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

En applicationcontext.xmlagregamos filtro para el paquete restante, excluyendo el controlador.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
Raje
fuente
99
por qué ? ¿Por qué no simplemente escanear todo una vez?
NimChimpsky
3
@NimChimpsky Debe escanear @Controllerbeans en contexto de servlet (requerido por Spring MVC).
Tuukka Mustonen
3
¿Por qué no puede todo el asunto dos veces? ¿Por qué incluir / excluir?
Mike Rylander
8
También se debe agregar el atributo use-default-filters = "false" en spring-servlet.xml
Rakesh Waghela
44
Rakesh Waghela tiene punto. Sin ese atributo, los beans de controlador se crearán dos veces. Primero en appContext y segundo en servletContext
UltraMaster
12

En palabras simples

applicationContext.xmldefine los beans que se comparten entre todos los servlets. Si su aplicación tiene más de un servlet, entonces defina los recursos comunes en elapplicationContext.xml tendría más sentido.

spring-servlet.xmldefine los beans que están relacionados solo con ese servlet. Aquí está el servlet del despachador. Por lo tanto, sus controladores Spring MVC deben estar definidos en este archivo.

No hay nada de malo en definir todos los beans en spring-servlet.xmlsi está ejecutando solo un servlet en su aplicación web.

Krishna
fuente
3
Puedo definir todos los beans en spring-servlet.xml, pero también debería haber applicationContext.xml que puede estar vacío (sin beans) en este caso. ¿Correcto?
Mikhail Kopylov
6

En la tecnología Servlet, si desea pasar cualquier entrada a un servlet en particular, debe pasar el parámetro init como se muestra a continuación.

 <servlet>
    <servlet-name>DBController</servlet-name>
    <servlet-class>com.test.controller.DBController</servlet-class>
    <init-param>
        <param-name>username</param-name>
        <param-value>John</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DBController</servlet-name>
    <url-pattern>/DBController</url-pattern>
</servlet-mapping>

Si desea pasar algo de entrada que es común para todos los servlets, entonces necesita configurar el parámetro de contexto. Ejemplo

 <context-param>
    <param-name>email</param-name>
    <param-value>admin@example.com</param-value>
</context-param>

Así que exactamente así cuando trabajamos con Spring MVC necesitamos proporcionar alguna información al servlet predefinido proporcionado por Spring que es DispatcherServlet a través de init param. Entonces, la configuración es en barbecho, aquí estamos proporcionando spring-servlet.xml como parámetro de inicio para DispatcherServlet.

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
              http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Spring MVC App</display-name>

    <servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
</web-app>

Nuevamente, necesitamos algunos parámetros de contexto. Eso es aplicable para toda la aplicación. Entonces podemos proporcionar el contexto raíz que es applicationcontext.xml. La configuración es así:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationcontext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
Rajanikanta Pradhan
fuente
4

Los contextos de aplicación proporcionan un medio para resolver mensajes de texto, incluido el soporte para i18n de esos mensajes. Los contextos de aplicación proporcionan una forma genérica de cargar recursos de archivos, como imágenes. Los contextos de aplicación pueden publicar eventos en beans que están registrados como oyentes. Ciertas operaciones en el contenedor o beans en el contenedor, que deben manejarse de manera programática con una fábrica de beans, pueden manejarse de manera declarativa en un contexto de aplicación. Soporte de ResourceLoader: Spring's Resource nos ofrece una abstracción genérica flexible para manejar recursos de bajo nivel. Un contexto de aplicación en sí mismo es un ResourceLoader, por lo tanto, proporciona una aplicación con acceso a instancias de recursos específicas de implementación. Soporte de MessageSource: el contexto de la aplicación implementa MessageSource, una interfaz utilizada para obtener mensajes localizados,

Sujata
fuente