Разница между applicationContext.xml и spring-servlet.xml в Spring Framework


373
  • Есть applicationContext.xmlи spring-servlet.xmlсвязаны так или иначе в Spring Framework?
  • Будут applicationContext.xmlли доступны файлы свойств, объявленные в DispatcherServlet?
  • На связанной ноте, зачем мне вообще нужен *-servlet.xml? Почему applicationContext.xmlодного недостаточно?

1
Смотрите это тоже. stackoverflow.com/questions/11708967/…
Санхьюн Ли

Ответы:


430

Spring позволяет определять несколько контекстов в иерархии родитель-потомок.

applicationContext.xmlОпределяет бобы для «корневого контекста WebAPP», то есть контекст , связанный с веб - приложение.

spring-servlet.xml(Или то , что вы называете это) определяет бобы для контекста приложения одного сервлета. В веб-приложении их может быть много, по одному на каждый сервлет Spring (например, spring1-servlet.xmlдля сервлета spring1, spring2-servlet.xmlдля сервлета spring2).

Бобы spring-servlet.xmlмогут ссылаться на бобы applicationContext.xml, но не наоборот.

Все контроллеры Spring MVC должны идти в spring-servlet.xmlконтексте.

В большинстве простых случаев applicationContext.xmlконтекст не нужен. Обычно используется для хранения bean-компонентов, которые совместно используются всеми сервлетами в веб-приложении. Если у вас есть только один сервлет, то в этом нет особого смысла, если только вы не используете его специально.


30
почему у вас есть несколько весенних сервлетов?
НимЧимпский

5
могучий мощный ответ (из-за краткости)
амфибия

35
@NimChimpsky иногда полезно отделить части вашего приложения, которые в противном случае могли бы конфликтовать в одном и том же контексте. Например, у вас могут быть службы ReST и стандартные представления, тогда у вас могут быть другие средства разрешения представлений или проблемы безопасности для служб в отношении представлений.
Бретт Райан

12
Люди должны увидеть этот ответ, прежде чем читать документацию и разрабатывать приложения! В обычных случаях вообще не нужно иметь ContextLoaderListener и contextConfigLocation, просто DispatcherServlet!
Руруський

24
Во многих руководствах contextConfigLocation содержит dispatcher-servlet.xml, а также DispatcherServlet. Это вызывает инициализацию бобов дважды!
Руруський

106

Сценарий 1

В клиентском приложении (приложение не является веб-приложением, например может быть приложением Swing)

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

context.getBean(name);

Нет необходимости в web.xml . ApplicationContext как контейнер для получения сервиса bean. Нет необходимости в контейнере веб-сервера. В test-client.xml может быть Simple bean без удаленного взаимодействия, bean с удаленным взаимодействием.

Вывод : в сценарии 1 applicationContext и DispatcherServletне связаны между собой.

Сценарий 2

В серверном приложении (приложение, развернутое на сервере, например, Tomcat). Доступ к услуге через удаленное взаимодействие из клиентской программы (например, приложение Swing)

Определить слушателя в web.xml

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

При запуске сервера ContextLoaderListenerсоздает экземпляры bean-компонентов, определенных в applicationContext.xml .

Предполагая, что вы определили следующее в applicationContext.xml :

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

Бины создаются из всех четырех файлов конфигурации test1.xml , test2.xml , test3.xml , test4.xml .

Вывод : в сценарии 2 applicationContext и DispatcherServletне связаны.

Сценарий 3

В веб-приложении с пружиной MVC.

В web.xml определите:

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

Когда Tomcat запускается, бины , определенные в springweb-servlet.xml , создаются. DispatcherServletрасширяется FrameworkServlet. В FrameworkServletбобовых инстанцирования происходит для Springweb. В нашем случае springweb - это FrameworkServlet.

Вывод : в сценарии 3 applicationContext и DispatcherServletне связаны.

Сценарий 4

В веб-приложении с пружиной MVC. springweb-servlet.xml для сервлета и applicationContext.xml для доступа к бизнес-службе в программе сервера или для доступа к службе БД в другой программе сервера.

В web.xml определены следующие:

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

При запуске сервера ContextLoaderListenerсоздает экземпляры bean-компонентов, определенных в applicationContext.xml ; при условии, что вы заявили здесь:

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

Все бины создаются из всех четырех test1.xml , test2.xml , test3.xml , test4.xml . После завершения создания экземпляра bean-компонента, определенного в applicationContext.xml , создаются экземпляры bean-компонента , определенные в springweb-servlet.xml .

Итак, порядок создания экземпляров: корень (контекст приложения), затем FrameworkServlet.

Теперь должно быть понятно, почему они важны в каком сценарии.


10
+1. Очень хорошо. Я искал этот тип сравнения, но так и не нашел.
Нинад Пингейл

@abishkar bhattarai очень хорошо, мой вопрос: так, что если использовать @ Component и аннотацию @ Value для создания бина, когда "Сценарий 4"
Лоуренс

Springweb DispatcherServletне будет вызываться, если URL не заканчивается на .action?
Асиф Муштак

@lawrence Вам все равно придется указать путь к классу в springweb-servlet.xml, чтобы Spring мог найти этот компонент при сканировании.
Веритас

54

Еще один момент, который я хочу добавить. В spring-servlet.xmlмы включаем компонент сканирования для пакета контроллера. В следующем примере мы включаем аннотацию фильтра для пакета контроллера.

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

В applicationcontext.xmlдобавляем фильтр для оставшегося пакета, исключая контроллер.

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

9
Почему ? Почему бы просто не отсканировать все это один раз?
НимЧимпский

3
@NimChimpsky Вы должны сканировать @Controllerbean-компоненты в контексте сервлета (требуется Spring MVC).
Туукка Мустонен

3
Почему не может все это дважды? Зачем включать / исключать?
Майк Риландер

8
Также следует добавить атрибут use-default-filters = "false" в spring-servlet.xml
Ракеш Вагела

4
Ракеш Вагела имеет точку. Без этого атрибута компоненты контроллера будут создаваться дважды. Во-первых, в appContext, а во-вторых, в servletContext
UltraMaster,

12

Проще говоря,

applicationContext.xmlопределяет бины, которые являются общими для всех сервлетов. Если ваше приложение имеет более одного сервлета, то определение общих ресурсов в applicationContext.xmlбудет более целесообразным.

spring-servlet.xmlопределяет бины, которые связаны только с этим сервлетом. Вот это диспетчерский сервлет. Итак, ваши Spring MVC контроллеры должны быть определены в этом файле.

Нет ничего плохого в определении всех bean-компонентов в том spring-servlet.xmlслучае, если в вашем веб-приложении запущен только один сервлет.


3
Я могу определить все bean-компоненты в spring-servlet.xml, но в этом случае также должен быть файл applicationContext.xml, который может быть пустым (без bean-компонентов). Правильный?
Михаил Копылов

6

В технологии Servlet, если вы хотите передать какой-либо ввод определенному сервлету, вам нужно передать параметр init, как показано ниже.

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

Если вы хотите передать некоторые данные, которые являются общими для всех сервлетов, тогда вам нужно настроить контекстные параметры. пример

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

Точно так же, когда мы работаем с Spring MVC, нам нужно предоставлять некоторую информацию в предопределенный сервлет, предоставляемый Spring, то есть DispatcherServlet, через initm параметр. Таким образом, конфигурация выглядит следующим образом: здесь мы предоставляем spring-servlet.xml в качестве параметра init для 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>

Снова нам нужен контекстный параметр. Это применимо для всего приложения. Таким образом, мы можем предоставить корневой контекст applicationcontext.xml. Конфигурация выглядит следующим образом:

    <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

Контексты приложения предоставляют средства для разрешения текстовых сообщений, включая поддержку i18n этих сообщений. Контексты приложения предоставляют общий способ загрузки файловых ресурсов, таких как изображения. Контексты приложения могут публиковать события в bean-компонентах, которые зарегистрированы как слушатели. Некоторые операции над контейнером или bean-компонентами в контейнере, которые должны выполняться программным способом с фабрикой bean-компонентов, могут быть декларативно обработаны в контексте приложения. Поддержка ResourceLoader. Ресурсный интерфейс Spring предоставляет гибкую универсальную абстракцию для обработки низкоуровневых ресурсов. Сам контекст приложения является ResourceLoader, следовательно, предоставляет приложению доступ к экземплярам ресурсов, специфичным для развертывания. Поддержка MessageSource: контекст приложения реализует MessageSource, интерфейс, используемый для получения локализованных сообщений,

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.