Роль / призначення ContextLoaderListener навесні?


169

Я вивчаю Spring Framework, який використовується в моєму проекті. Я знайшов запис ContextLoaderListener у своєму файлі web.xml . Але не могли зрозуміти, як саме це допомагає розробнику?

В офіційній документації ContextLoaderListener сказано, що слід запустити WebApplicationContext . Щодо WebApplicationContext JavaDocs кажуть:

Інтерфейс для забезпечення конфігурації веб-програми.


Але я не в змозі зрозуміти, чого я досягаю з ContextLoaderListener, який внутрішньо ініціалізує WebApplicationContext ?

Згідно з моїм відчуттям , ContextLoaderListener зчитує файл конфігурації Spring (зі значенням даного проти contextConfigLocation в web.xml ), аналізує його і завантажує одноточечного бобу визначається в цьому файлі конфігурації. Аналогічно, коли ми хочемо завантажити прототип bean , ми будемо використовувати той самий контекст webapplication, щоб завантажити його. Таким чином, ми ініціалізуємо webapplication з ContextLoaderListener, щоб ми заздалегідь читали / розбирали / перевіряли конфігураційний файл і кожного разу, коли ми хочемо ввести залежність, ми можемо це зробити негайно. Чи правильно це розуміння?


1
хтось може мені повідомити різницю між RequestContextListener та ContextLoaderListener
VdeX

Відповіді:


111

Ваше розуміння правильне. Там ApplicationContextживуть ваші весняні боби. Призначення проекту ContextLoaderListenerдвояке:

  1. прив’язати життєвий цикл ApplicationContextдо життєвого циклу ServletContextта

  2. щоб автоматизувати створення ApplicationContext, тому вам не потрібно писати явний код, щоб створити його - це функція зручності.

Ще одна зручна річ про ContextLoaderListenerте , що він створює WebApplicationContextі WebApplicationContextзабезпечує доступ до ServletContextчерез ServletContextAwareквасолею і getServletContextметод.


2
У мене є сумніви щодо вашого другого пункту. Ви сказали, що ServletContextListener забезпечує доступ до ServletContext. Але, навіть якщо web.xml не має ServletContextListener, доступ до ServletContext можна отримати через WebApplicationContext (WebApplicationContext має бути автоматичним провідником). Отже, що саме це стосується ServletContext?
Суміт Дезай

Це створює WebApplicationContext. Інакше його потрібно було б створити вручну.
sourcedelica

чи ContextLoaderListenerреалізує метод знищення для знищення всіх бобів, коли веб-контейнер вимикається?
асгс

так - це робить, коли contextDestroyedвикликається. Див. Документи API.
sourcedelica

@sourcedelica У мене є сумніви, прочитавши це, я перевірив свої додатки web.xml. У моєму xml-файлі є два слухачі ContextLoaderListenerі DispatcherServlet. Тому я думаю, що в обох немає потреби, чи безпечно це видалити, ContextLoaderListenerчому я прошу, тому що заявка живе з 7-8 місяців. web.xml тут для вашої довідки.
Amogh

43

ContextLoaderListenerє необов'язковим . Просто щоб зробити пункт тут: ви можете завантажити прикладну Spring ніколи не настройки ContextLoaderListener, тільки базовий мінімум web.xmlз DispatcherServlet.

Ось як це виглядатиме:

web.xml

<?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_2_5.xsd" 
    id="WebApp_ID" 
    version="2.5">
  <display-name>Some Minimal Webapp</display-name>
  <welcome-file-list>   
    <welcome-file>index.jsp</welcome-file>    
  </welcome-file-list>

  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>

Створіть названий файл dispatcher-servlet.xmlі збережіть його під WEB-INF. Оскільки ми згадували index.jspу вітальному списку, додайте цей файл підWEB-INF .

диспетчер-сервлет.xml

У dispatcher-servlet.xmlвизначте вашу квасолю:

<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd     
        http://www.springframework.org/schema/context     
        http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="bean1">
      ...
    </bean>
    <bean id="bean2">
      ...
    </bean>         

    <context:component-scan base-package="com.example" />
    <!-- Import your other configuration files too -->
    <import resource="other-configs.xml"/>
    <import resource="some-other-config.xml"/>

    <!-- View Resolver -->
    <bean 
        id="viewResolver" 
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
      <property 
          name="viewClass" 
          value="org.springframework.web.servlet.view.JstlView" />
      <property name="prefix" value="/WEB-INF/jsp/" />
      <property name="suffix" value=".jsp" />
    </bean>
</beans>

2
Якщо це необов’язково, коли ви хочете його використовувати? Здається, Spring Security вимагає від нього використання DelegatingFilterProxy.
Девід

6
Ви повинні використовувати його, коли ви хочете розмістити файл сервлетів у вашому користувальницькому місці чи зі спеціальним іменем, а не за замовчуванням "[servlet-name] -servlet.xml" та шлях у розділі "Web-INF /"
Рамеш Карна

Чи добре визначити bean в диспетчері-servlet.xml, ніж applicationContext.xml?
Четанський Гол

8
Зазвичай квасоля краще розподілити, відображаючи шари архітектури вашої програми. Боби для шару презентації (наприклад, контролери mvc) можуть бути в диспетчері-servlet.xml. Боби, що належать до рівня обслуговування, повинні бути визначені applicationContext.xml. Це не суворе правило, але це хороша практика, щоб досягти роз'єднання проблем.
Клаудіо Вентуріні

2
@Ramesh Karna Я не думаю, що це потрібно для зміни імені та місцезнаходження. Я думаю, що це потрібно, коли ми ініціалізуємо кілька сервлетів Dispatcher і все ще хочемо, щоб контекст Root був спільним для всіх контекстів DispaterServlets, тоді нам потрібно використовувати ContextLoaderListener.
наднова

23

Для простої програми Spring, вам не потрібно визначати ContextLoaderListenerсвою web.xml; ви можете просто помістити всі файли конфігурації Spring у <servlet>:

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/mvc-core-config.xml, classpath:spring/business-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Для більш складної програми Spring, де у вас є декілька DispatcherServletвизначених, ви можете мати спільні файли конфігурації Spring, якими спільно користуватися всі DispatcherServletвизначені в ContextLoaderListener:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/common-config.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>mvc1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/mvc1-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>mvc2</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/mvc2-config.xmll</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Просто майте на увазі, ContextLoaderListenerвиконує фактичну роботу ініціалізації для контексту кореневої програми.

Я виявив, що ця стаття дуже допомагає: Spring MVC - Контекст програм проти контексту веб-додатків


Стаття, що поділяється тут, справді забезпечує глибоке розуміння понять
Приянк Таккар

10

Блог " Призначення ContextLoaderListener - Spring MVC " дає дуже хороші пояснення.

Згідно з цим, Application-Contexts є ієрархіальним, а отже, контекст DispatcherSerlvet стає дочірнім контекстом ContextLoaderListener. Завдяки чому технологія, що використовується в шарі контролера (Struts або Spring MVC), може залежати від кореневого контексту, створеного ContextLoaderListener.


Дякую за те, що поділився ним приятель .. :)
Діпак Кумар

3

Якщо ви хочете розмістити файл сервлету у вашому користувальницькому розташуванні або зі спеціальним іменем, а не в умовному режимі іменування за замовчуванням [servletname]-servlet.xmlта під ним Web-INF/, ви можете використовувати ContextLoaderListener.


3

ContextLoaderListner - слухач сервлетів, який завантажує всі різні файли конфігурації (конфігурація службового рівня, конфігурація шару стійкості тощо) в єдиний весняний контекст програми.

Це допомагає розділити весняні конфігурації на декілька файлів XML.

Після завантаження файлів контексту Spring створює об’єкт WebApplicationContext на основі визначення bean і зберігає його у ServletContext вашого веб-додатку.


3

введіть тут опис зображенняЦей слухач Bootstrap повинен запустити та вимкнути корінь Spring веб-код WebApplicationContext. Оскільки веб-додаток може мати декілька сервертів диспетчера, і кожен з них має власний контекст програми, що містить контролери, перетворювач перегляду, відображення обробника тощо. контекст програми, створений диспетчерськими сервлетами).

Друге використання цього слухача - це коли ви хочете використовувати захист весни.


3

Корінни та дочірні контексти Перш ніж читати далі, будь ласка, розумійте це -

Весна може мати декілька контекстів одночасно. Один з них буде кореневим контекстом, а всі інші контексти - це дочірніми контекстами.

Усі дочірні контексти можуть отримати доступ до бобів, визначених у кореневому контексті; але навпаки не вірно. Корінний контекст не може отримати доступ до дочірніх бобів.

ApplicationContext:

applicationContext.xml - це коренева конфігурація контексту для кожної веб-програми. Весна завантажує файл applicationContext.xml і створює ApplicationContext для всієї програми. Буде лише один контекст програми для кожної веб-програми. Якщо ви явно не оголосили ім’я файлу конфігурації контексту в web.xml за допомогою параметраComfigLocation, параметр Spring буде шукати applicationContext.xml у папці WEB-INF та видалить FileNotFoundException, якщо він не зміг знайти цей файл.

ContextLoaderListener Виконує фактичну роботу ініціалізації для контексту кореневої програми. Читає контекст-парам "contextConfigLocation" і передає його значення екземпляру контексту, аналізуючи його на потенційно декілька шляхів до файлів, які можна розділити будь-якою кількістю коми і пробілів, наприклад "WEB-INF / applicationContext1.xml, WEB-INF / applicationContext2.xml ”. ContextLoaderListener необов’язковий. Просто для зауваження тут: ви можете завантажувати додаток Spring, не налаштовуючи ContextLoaderListener, просто основний мінімум web.xml за допомогою DispatcherServlet.

DispatcherServlet DispatcherServlet по суті є сервлетом (він розширює HttpServlet), основною метою якого є обробка вхідних веб-запитів, що відповідають налаштованому шаблону URL. Знадобиться вхідний URI і знайти правильну комбінацію контролера та перегляду. Так це передній контролер.

Коли ви визначаєте DispatcherServlet у весняній конфігурації, ви надаєте XML-файл із записами класів контролерів, переглядає відображення тощо, використовуючи атрибут contextConfigLocation.

Крім ApplicationContext, в одній веб-програмі може бути декілька WebApplicationContext. Простими словами, кожен DispatcherServlet пов'язаний з одним WebApplicationContext. Файл xxx-servlet.xml специфічний для DispatcherServlet, а веб-додаток може мати більше одного DispatcherServlet, налаштованого для обробки запитів. У таких сценаріях кожен DispatcherServlet матиме окремий xxx-servlet.xml. Але, applicationContext.xml буде загальним для всіх файлів конфігурації сервлетів. Весна за замовчуванням завантажить файл з назвою "xxx-servlet.xml" з папки WEB-INF webapps, де xxx - ім'я сервлета в web.xml. Якщо ви хочете змінити ім'я цього імені файлу або змінити місце розташування, додайте ініціатор-парам з контекстуванням ConfigLocation як ім'я парам.

Порівняння та відношення між ними:

ContextLoaderListener vs DispatcherServlet

ContextLoaderListener створює контекст кореневої програми. Записи DispatcherServlet створюють один дочірній контекст програми на кожну запис сервлета. Дочірні контексти можуть отримати доступ до бобів, визначених у кореневому контексті. Квасоля в кореневому контексті не може отримати доступ до бобів у дочірніх контекстах (безпосередньо). Усі контексти додаються до ServletContext. Ви можете отримати доступ до кореневого контексту за допомогою класу WebApplicationContextUtils.

Прочитавши весняну документацію, розуміємо наступне:

a) Контексти програми є ієрархіальними, а також WebApplicationContexts. Зверніться до документації тут.

b) ContextLoaderListener створює кореневий веб-додаток-контекст для веб-програми та розміщує його в ServletContext. Цей контекст може бути використаний для завантаження та вивантаження пружинних бобів, незалежно від того, яка технологія використовується в шарі контролера (Struts або Spring MVC).

c) DispatcherServlet створює власний WebApplicationContext, а обробники / контролери / вирішальники перегляду керуються цим контекстом.

d) Коли ContextLoaderListener використовується в тандемі з DispatcherServlet, кореневий веб-додаток-контекст створюється спочатку, як було сказано раніше, а дочірній контекст також створюється DispatcherSerlvet і додається до кореневого контексту програми. Зверніться до документації тут.

Коли ми працюємо з Spring MVC і також використовуємо Spring на рівні послуг, ми надаємо два контексти програми. Перший налаштований за допомогою ContextLoaderListener, а другий за допомогою DispatcherServlet

Як правило, ви визначатимете всі пов'язані з MVC боби (контролер та перегляди тощо) у контексті DispatcherServlet, а також всі наскрізні боби, такі як безпека, транзакції, послуги тощо у кореневому контексті ContextLoaderListener.

Докладнішу інформацію див. На веб-сторінці : https://siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html


2

В основному ви можете ізолювати контекст кореневої програми та контекст веб-додатків за допомогою ContextLoaderListner.

Конфігураційний файл, відображений з контекстним парам, поводитиметься як конфігурація контексту кореневої програми. І конфігураційний файл, зіставлений з диспетчерським сервлетом, буде вести себе як контекст веб-додатків.

У будь-якій веб-програмі ми можемо мати кілька диспетчерських сервлетів, тому безліч контекстів веб-додатків.

Але в будь-якій веб-програмі ми можемо мати лише один контекст кореневого додатка, який поділяється з усіма контекстами веб-додатків.

Ми повинні визначати наші спільні служби, сутності, аспекти тощо у кореневому застосуванні. А контролери, перехоплювачі тощо знаходяться у відповідному контексті веб-додатків.

Зразок web.xml є

<!-- language: xml -->
<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>example.config.AppConfig</param-value>
    </context-param>
    <servlet>
        <servlet-name>restEntryPoint</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>example.config.RestConfig</param-value>
        </init-param>       
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>restEntryPoint</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>webEntryPoint</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>example.config.WebConfig</param-value>
        </init-param>       
        <load-on-startup>1</load-on-startup>
    </servlet>  
    <servlet-mapping>
        <servlet-name>webEntryPoint</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app> 

Тут конфігураційний клас example.config.AppConfig можна використовувати для налаштування служб, сутностей, аспектів тощо в контексті кореневих додатків, які будуть спільними з усіма іншими контекстами веб-додатків (наприклад, у нас є два конфігураційні класи конфігурації веб-додатків RestConfig і WebConfig)

PS: Тут ContextLoaderListener абсолютно необов’язковий. Якщо ми не будемо згадувати ContextLoaderListener в web.xml тут, AppConfig не працюватиме. У цьому випадку нам потрібно налаштувати всі наші сервіси та об'єкти в WebConfig та Rest Config.


1

Це дасть вам змогу підключити код, який ви хочете виконати під час розгортання веб-додатків


Jigar, насправді це те, що я намагаюся дізнатись. Яку особливість забезпечує клас завантажувача контексту за замовчуванням у час розгортання?
M Sach

Зміна властивостей / XML-файлів і дозволити їх перезавантажувати під час виконання програми без перезавантаження сервера
vsingh

1

Клас слухача - слухає подію (наприклад, запуск / вимкнення сервера)

ContextLoaderListener -

  1. Слухає під час запуску / відключення сервера
  2. Приймає файли конфігурації Spring як вхідні дані і створює боби відповідно до конфігурації та робить їх готовими (знищує боб під час вимкнення)
  3. Файли конфігурації можна надати так у веб.xml

    <param-name>contextConfigLocation</param-name>  
    <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>  

1

У контексті весняної рамки метою ContextLoaderListener є завантаження інших бобів у вашому додатку, таких як компоненти середнього рівня та рівні рівня даних, які керують задньою частиною програми.


0

Ваше розуміння правильне. Цікаво, чому ви не бачите жодних переваг у ContextLoaderListener. Наприклад, вам потрібно побудувати фабрику сеансів (для управління базою даних). Ця операція може зайняти деякий час, тому краще робити це при запуску. Звичайно, ви можете зробити це за допомогою сервісів init або чогось іншого, але перевага Spring-підходу полягає в тому, що ви робите конфігурацію без написання коду.


0

Якщо ми пишемо web.xml без ContextLoaderListener, тоді ми не можемо дати атестування, використовуючи customAuthenticationProvider у захисті весни. Оскільки DispatcherServelet є дочірнім контекстом ContextLoaderListener, customAuthenticationProvider є частиною parentContext, яка є ContextLoaderListener. Отже, батьківський контекст не може мати залежності від дитячого контексту. І тому найкраще практику писати spring-context.xml в contextparam, а не писати в initparam.


0

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

<context-param><param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/training-service.xml, /WEB-INF/training-data.xml</param-value> </context-param>

Інший підхід до ContextLoaderListener - це використання ContextLoaderServlet, як показано нижче

<servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>

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