Різниця між 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 / ...
Sanghyun Lee

Відповіді:


430

Весна дозволяє визначати кілька контекстів в ієрархії батько-дитина.

applicationContext.xmlВизначає боби для «кореневого контексту WebAPP», тобто контекст , пов'язаний з веб - додаток.

spring-servlet.xml(Або то , що ви називаєте це) визначає боби для контексту програми одного сервлету. Їх може бути багато в webapp, по одному на весняний сервлет (наприклад, spring1-servlet.xmlдля сервлета spring1, spring2-servlet.xmlсервлета spring2).

Квасоля spring-servlet.xmlможе посилатися на квасоля applicationContext.xml, але не навпаки.

Усі весняні контролери MVC повинні йти в spring-servlet.xmlконтексті.

У більшості простих випадків applicationContext.xmlконтекст є непотрібним. Зазвичай він використовується для зберігання квасолі, яка поділяється між усіма сервлетами в webapp. Якщо у вас є лише один сервлет, то це не так вже й багато сенсу, якщо ви не маєте для нього конкретного використання.


30
чому б у вас було декілька весняних сервлетів?
NimChimpsky

5
могутня потужна відповідь (через
стислість

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

12
Люди повинні побачити цю відповідь, перш ніж читати документацію та розробляти додатки! У звичайних випадках не потрібно взагалі мати ContextLoaderListener та contextConfigLocation, просто DispatcherServlet!
руруський

24
У багатьох підручниках контекстConfigLocation містить диспетчер-servlet.xml, а також DispatcherServlet. Це спричиняє ініціалізацію бобів двічі!
руруський

106

Сценарій 1

У клієнтській програмі (додаток не веб-додаток, наприклад, програма swing)

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

context.getBean(name);

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

Висновок : У сценарії 1 додатокКонтекст і DispatcherServletне пов'язані між собою.

Сценарій 2

У серверній програмі (програма, розгорнута на сервері, наприклад, Tomcat). Доступ до служби за допомогою видалення з клієнтської програми (наприклад, програма Swing)

Визначте слухача в web.xml

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

При запуску сервера ContextLoaderListenerінстанціює боби, визначені в 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 застосуванняКонтекст і 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 - це FrameworkServlet.

Висновок : У сценарії 3 застосуванняКонтекст і 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інстанціює боби, визначені в 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 . Після завершення опису бобів, визначеного в applicationContext.xml , квасоля, визначена у Springweb-servlet.xml , інстанціюється.

Отже, порядок інсталяції такий: корінь (контекст програми), потім FrameworkServlet.

Тепер має бути зрозуміло, чому вони важливі в якому сценарії.


10
+1. Дуже добре. Я шукав цей тип порівняння, але так і не знайшов.
Нінад Пінгале

@abishkar bhattarai дуже добре, моє запитання таке: то що робити, якщо використовувати @ Component та @ Value анотацію для створення квасолі, коли "Сценарій 4"
Lawrence

springweb DispatcherServletне зателефонує, якщо URL не закінчується .action?
Асиф Муштак

@lawrence Ще потрібно буде вказати шлях класу у springweb-servlet.xml, щоб Spring міг знайти цей компонент у своєму скануванні.
veritas

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
чому? Чому б просто не сканувати всю справу один раз?
NimChimpsky

3
@NimChimpsky Вам потрібно сканувати @Controllerквасоля в контексті сервлетів (вимагається Spring MVC).
Tuukka Mustonen

3
Чому не можна зробити всю справу двічі? Навіщо включати / виключати?
Майк Райландер

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

4
Ракеш Вагела має точку. Без цього атрибуту боби Controller будуть створені двічі. По-перше в appContext, а по-друге в servletContext
UltraMaster

12

Простими словами,

applicationContext.xmlвизначає квасоля, яку поділяють між усіма сервлетами. Якщо у вашій програмі є більше одного сервлета, то визначте загальні ресурси вapplicationContext.xml має більше сенсу.

spring-servlet.xmlвизначає квасоля, яка пов'язана лише з цим сервлетом. Ось це серветка диспетчера. Отже, ваші контролери Spring MVC повинні бути визначені у цьому файлі.

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


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

6

У сервлет-технології, якщо ви хочете передати будь-який вхід певному сервлету, вам потрібно передати параметр 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>

Якщо ви хочете передати частину put, яка є загальною для всіх сервлетів, тоді вам потрібно налаштувати контекстну параму. Приклад

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

Так саме так, коли колись ми працюємо з Spring MVC, нам потрібно надати певну інформацію попередньо визначеному сервлету, наданому Spring, що є DispatcherServlet через init param. Таким чином, конфігурація є такою, як пара, тут ми надаємо 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 цих повідомлень. Контексти додатків забезпечують загальний спосіб завантаження файлових ресурсів, таких як зображення. Контексти програм можуть публікувати події для бобів, які зареєстровані як слухачі. Деякі операції з контейнером або квасолею в контейнері, з якими програмувати потрібно програмно з фабрикою фасолі, можна обробляти декларативно в контексті програми. Підтримка ResourceLoader: Інтерфейс Spring's Resource використовує нам гнучку загальну абстракцію для обробки ресурсів низького рівня. Контекст програми сам по собі є ResourceLoader, отже, надає програмі доступ до екземплярів ресурсу, що залежить від розгортання. Підтримка MessageSource: контекст програми реалізує MessageSource, інтерфейс, який використовується для отримання локалізованих повідомлень,

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.