Diferença entre applicationContext.xml e spring-servlet.xml no Spring Framework


373
  • São applicationContext.xmle estão spring-servlet.xmlrelacionados de qualquer maneira no Spring Framework?
  • Os arquivos de propriedades declarados em applicationContext.xmlestarão disponíveis para DispatcherServlet?
  • Em uma nota relacionada, por que eu preciso de um *-servlet.xml? Por que applicationContext.xmlsozinho não é suficiente?

Respostas:


430

O Spring permite definir vários contextos em uma hierarquia pai-filho.

O applicationContext.xmldefine os beans para o "contexto do webapp raiz", ou seja, o contexto associado ao webapp.

O spring-servlet.xml(ou o que você chamar) define os beans para o contexto de aplicativo de um servlet. Pode haver muitos deles em um aplicativo da web, um por servlet Spring (por exemplo, spring1-servlet.xmlpara servlet spring1, spring2-servlet.xmlpara servlet spring2).

Beans in spring-servlet.xmlpode fazer referência a beans applicationContext.xml, mas não vice-versa.

Todos os controladores Spring MVC devem estar no spring-servlet.xmlcontexto.

Na maioria dos casos simples, o applicationContext.xmlcontexto é desnecessário. Geralmente, é usado para conter beans compartilhados entre todos os servlets em um aplicativo da web. Se você tiver apenas um servlet, não há muito sentido, a menos que você tenha um uso específico para ele.


30
por que você teria vários servlets de mola?
NimChimpsky

5
resposta poderosa e potente (por causa da sucintividade) #
611

35
@NimChimpsky, às vezes é útil separar partes do seu aplicativo que poderiam entrar em conflito no mesmo contexto. Como exemplo, você pode ter serviços ReST e exibições padrão, pode ter diferentes resolvedores de exibição ou preocupações de segurança para os serviços quanto às exibições.
Brett Ryan #

12
As pessoas devem ver esta resposta antes de ler a documentação e desenvolver aplicativos! Em casos normais, não há necessidade de ContextLoaderListener e contextConfigLocation, apenas DispatcherServlet!
ruruskyi

24
Em muitos tutoriais, contextConfigLocation contém dispatcher-servlet.xml e DispatcherServlet. Isso faz com que os beans sejam inicializados duas vezes!
ruruskyi

106

Cenário 1

No aplicativo cliente (o aplicativo não é um aplicativo da web, por exemplo, pode ser um aplicativo swing)

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

context.getBean(name);

Não há necessidade de web.xml . ApplicationContext como contêiner para obter o serviço de bean. Não há necessidade de contêiner de servidor da web. No test-client.xml , pode haver bean Simples sem controle remoto , bean com controle remoto .

Conclusão : No cenário 1 applicationContext e DispatcherServletnão estão relacionados.

Cenário 2

Em um aplicativo de servidor (aplicativo implantado no servidor, por exemplo, Tomcat). Serviço acessado via comunicação remota do programa cliente (por exemplo, aplicativo Swing)

Definir ouvinte no web.xml

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

Na inicialização do servidor, ContextLoaderListenerinstancia os beans definidos em applicationContext.xml .

Supondo que você tenha definido o seguinte em applicationContext.xml :

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

Os beans são instanciados a partir dos quatro arquivos de configuração test1.xml , test2.xml , test3.xml , test4.xml .

Conclusão : No cenário 2 applicationContext e DispatcherServletnão estão relacionados.

Cenário 3

Em um aplicativo da web com o Spring MVC.

No web.xml, defina:

<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>

Quando o Tomcat é iniciado, os beans definidos no springweb-servlet.xml são instanciados. DispatcherServletse estende FrameworkServlet. No FrameworkServletbean, a instanciação ocorre para a mola. No nosso caso, springweb é FrameworkServlet.

Conclusão : No cenário 3 applicationContext e DispatcherServletnão estão relacionados.

Cenário 4

Em aplicativo da web com Spring MVC. springweb-servlet.xml para servlet e applicationContext.xml para acessar o serviço de negócios no programa do servidor ou para acessar o serviço DB em outro programa do servidor.

No web.xml, são definidos os seguintes:

<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>

Na inicialização do servidor, ContextLoaderListenerinstancia os beans definidos em applicationContext.xml ; supondo que você tenha declarado aqui:

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

Os beans são todos instanciados dos quatro test1.xml , test2.xml , test3.xml , test4.xml . Após a conclusão da instanciação de bean definida em applicationContext.xml , os beans definidos em springweb-servlet.xml são instanciados.

Portanto, a ordem da instanciação é: a raiz (contexto do aplicativo) e, em seguida, FrameworkServlet.

Agora deve ficar claro por que eles são importantes em que cenário.


10
+1. Muito bom. Estava procurando esse tipo de comparação, mas nunca o encontrei.
Ninad Pingale

@abishkar Bhattarai muito bom, a minha pergunta é: então o que é se usando @ Component e @ Valor anotação para criar feijão quando "Cenário 4"
Lawrence

springweb DispatcherServletnão será chamado se o URL não terminar com .action?
Asif Mushtaq

@lawrence Você ainda precisará especificar o caminho da classe no springweb-servlet.xml, para que o Spring possa encontrar esse componente em sua verificação.
veritas

54

Mais um ponto que quero acrescentar. Em spring-servlet.xmlque incluem verificação de componente para o pacote Controller. No exemplo a seguir, incluímos anotação de filtro para o pacote do 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>

Em applicationcontext.xmlsomarmos filtro para restante do pacote excluindo controlador.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

9
porque ? Por que não apenas escanear a coisa toda uma vez?
NimChimpsky

3
@NimChimpsky Você precisa varrer @Controllerbeans no contexto de servlet (exigido pelo Spring MVC).
Tuukka Mustonen

3
Por que não pode a coisa toda duas vezes? Por que incluir / excluir?
Mike Rylander

8
Deve-se também adicionar uso-default-filtros = atributo "false" na primavera-servlet.xml
Rakesh Waghela

4
Rakesh Waghela tem razão. Sem esse atributo, os beans do Controller serão criados duas vezes. Primeiramente no appContext e depois no servletContext
UltraMaster

12

Em palavras simples,

applicationContext.xmldefine os beans que são compartilhados entre todos os servlets. Se o seu aplicativo tiver mais de um servlet, definir os recursos comuns no applicationContext.xmlfaria mais sentido.

spring-servlet.xmldefine os beans que estão relacionados apenas a esse servlet. Aqui está o servlet do expedidor. Portanto, seus controladores Spring MVC devem ser definidos neste arquivo.

Não há nada errado em definir todos os beans no spring-servlet.xmlse você estiver executando apenas um servlet em seu aplicativo da web.


3
Posso definir todos os beans em spring-servlet.xml, mas também deve haver applicationContext.xml que pode estar vazio (sem beans) nesse caso. Corrigir?
Mikhail Kopylov

6

Na tecnologia Servlet, se você quiser passar qualquer entrada para um servlet específico, precisará passar no parâmetro init como no código abaixo.

 <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>

Se você deseja passar algo em comum que é comum a todos os servlets, nesse momento, é necessário configurar os parâmetros de contexto. Exemplo

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

Portanto, exatamente assim, sempre que estivermos trabalhando com o Spring MVC, precisamos fornecer algumas informações ao servlet predefinido fornecido pelo Spring, que é o DispatcherServlet através do parâmetro init. Portanto, a configuração é como fallows, aqui estamos fornecendo o spring-servlet.xml como parâmetro init 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>

Novamente, precisamos de alguns parâmetros de contexto. Isso é aplicável para toda a aplicação. Portanto, podemos fornecer o contexto raiz que é applicationcontext.xml A configuração é assim:

    <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>

4

Os contextos de aplicativos fornecem um meio para resolver mensagens de texto, incluindo o suporte ao i18n dessas mensagens. Os contextos de aplicativos fornecem uma maneira genérica de carregar recursos de arquivos, como imagens. Os contextos de aplicativos podem publicar eventos em beans registrados como ouvintes. Certas operações no contêiner ou feijões no contêiner, que precisam ser manipuladas de maneira programática com uma fábrica de feijões, podem ser manipuladas declarativamente em um contexto de aplicativo. Suporte ao ResourceLoader: o recurso da Spring cria uma interface genérica flexível para manipular recursos de baixo nível. Um contexto de aplicativo em si é um ResourceLoader, portanto, fornece um aplicativo com acesso a instâncias de recursos específicas da implantação. Suporte ao MessageSource: o contexto do aplicativo implementa o MessageSource, uma interface usada para obter mensagens localizadas,

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.