ContextLoaderListener'ın İlkbahardaki Rolü / Amacı?


169

Projemde kullanılan Spring Framework'ü öğreniyorum . ContextLoaderListener girdisini web.xml dosyamda buldum . Ancak bir geliştiriciye tam olarak nasıl yardımcı olduğunu bulamadınız mı?

ContextLoaderListener'ın resmi belgelerinde WebApplicationContext'i başlatmanın uygun olduğunu söylüyor . WebApplicationContext JavaDocs ile ilgili olarak :

Bir web uygulaması için yapılandırma sağlayan arayüz.


Ancak , dahili olarak WebApplicationContext'i başlatan ContextLoaderListener ile ne başardığımı anlayamıyorum ?

Benim anlayış gereğince , ContextLoaderListener (içinde contextConfigLocation karşı verilen değerle Bahar yapılandırma dosyasını okur web.xml ) ve yükler ayrıştırır tekil fasulye o yapılandırma dosyasında tanımlanan. Benzer şekilde, prototip fasulye yüklemek istediğimizde, yüklemek için aynı web uygulaması bağlamını kullanacağız. Bu nedenle ContextLoaderListener ile web uygulamasını başlatırız, böylece yapılandırma dosyasını önceden okur / ayrıştırır / doğrularız ve bağımlılığı enjekte etmek istediğimizde bunu derhal gecikmeden yapabiliriz. Bu anlayış doğru mu?


1
herkes RequestContextListener ve ContextLoaderListener
VdeX

Yanıtlar:


111

Anlayışınız doğru. ApplicationContextSenin Bahar fasulye canlı yerdir. Amacı ContextLoaderListeneriki yönlüdür:

  1. yaşam döngüsünü ve yaşam döngüsüne bağlamak ApplicationContextiçin ServletContextve

  2. oluşturulmasını otomatikleştirmek için ApplicationContext, onu oluşturmak için açık kod yazmak zorunda değilsiniz - bu bir kolaylık işlevidir.

Hakkında başka uygun bir şey ContextLoaderListenerbir yaratmasıdır WebApplicationContextve WebApplicationContexterişim sağlar ServletContextaracılığıyla ServletContextAwarefasulye ve getServletContextyöntemle.


2
İkinci noktanla ilgili bir şüphem var. ServletContextListener'ın ServletContext'e erişim sağladığını söylediniz. Ancak, web.xml dosyasında ServletContextListener olmasa bile, ServletContext'e WebApplicationContext üzerinden erişilebilir (WebApplicationContext otomatik olarak bağlanır). Peki, ServletContext ile tam olarak ne ilgisi var?
Sumit Desai

Oluşturur WebApplicationContext. Aksi takdirde manuel olarak oluşturulması gerekir.
sourcedelica

yok ContextLoaderListenerolduğunda web konteyner kapanır aşağı bütün fasulye yok etmek için bir imha yöntemi uygulamak?
Eylül'de

evet - contextDestroyedçağrıldığında bunu yapar . API belgelerine bakın.
sourcedelica

@sourcedelica Bunu okuduktan sonra bir şüphem var benim uygulamalarımı kontrol ettim web.xml. Xml dosyamda iki dinleyici var ContextLoaderListenerve DispatcherServlet. Yani her ikisine de gerek yok, ContextLoaderListenerneden sorduğumu kaldırmak güvenli mi çünkü uygulama 7-8 aydan beri yaşıyor. web.xml referansınız için burada .
Amogh

43

ContextLoaderListenerbir isteğe bağlı . Sadece burada bir noktaya değinmek için: bir Spring uygulamasını hiç yapılandırmadan ContextLoaderListener, sadece temel bir minimum web.xmlile başlatabilirsiniz DispatcherServlet.

İşte neye benzeyeceği:

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>

Adlı bir dosya oluşturun dispatcher-servlet.xmlve altında saklayın WEB-INF. index.jspKarşılama listesinde belirttiğimiz için bu dosyayı altına ekleyin WEB-INF.

hareket memuru-servlet.xml

In dispatcher-servlet.xmlfasulyenin tanımlayın:

<?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
İsteğe bağlıysa, ne zaman kullanmak istersiniz ? Görünüşe göre Spring Security, DelegatingFilterProxy'yi kullanmasını gerektiriyor.
David

6
Servlet dosyanızı "[servlet-adı] -servlet.xml" varsayılan adı ve "Web-INF /" altındaki yol yerine özel konumunuza veya özel adla koymak istediğinizde kullanmanız gerekir
Ramesh Karna

Bean'i dispatcher-servlet.xml dosyasında applicationContext.xml dosyasından tanımlamak iyi bir fikir mi?
Chetan Gole

8
Genellikle fasulyeleri uygulamanızın mimarisinin katmanlarını yansıtarak dağıtmak daha iyidir. Sunum katmanı çekirdekleri (örneğin mvc denetleyicileri) dispatcher-servlet.xml dosyasında olabilir. Servis katmanına ait fasulye applicationContext.xml olarak tanımlanmalıdır. Bu katı bir kural değil, ancak endişelerin ayrılmasını sağlamak için iyi bir uygulamadır.
Claudio Venturini

2
@Ramesh Karna İsim ve yer değişikliği için gerekli olduğunu düşünmüyorum. Birden fazla Dispatcher sunucu uygulaması başlatırken yine de bir Kök bağlamın tüm DispaterServlet'lerin kendi bağlamı tarafından paylaşılmasını istediğimizde ContextLoaderListener kullanmamız gerektiğini düşünüyorum.
süpernova

23

Basit bir Bahar uygulaması ContextLoaderListeneriçin web.xml; tüm Spring yapılandırma dosyalarınızı buraya koyabilirsiniz <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>

Birden var daha karmaşık Bahar uygulaması için DispatcherServlettanımlanan tüm tarafından paylaşılan ortak Bahar yapılandırma dosyalarını olabilir DispatcherServlettanımlanan 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>

Unutmayın, kök uygulama bağlamı ContextLoaderListeneriçin gerçek başlatma işini gerçekleştirir .

Bu makalenin çok yardımcı olduğunu buldum: Bahar MVC - Uygulama Bağlamı vs Web Uygulama Bağlamı


burada paylaşılan makale gerçekten kavramların derinlemesine anlaşılmasını sağlar
Priyank Thakkar

10

" ContextLoaderListener'ın Amacı - Spring MVC adlı blog çok iyi bir açıklama veriyor.

Buna göre, Uygulama Bağlamları hiyerarşiktir ve dolayısıyla DispatcherSerlvet'in bağlamı ContextLoaderListener bağlamının alt öğesi olur. Bu nedenle, kontrolör katmanında (Struts veya Spring MVC) kullanılan teknoloji ContextLoaderListener tarafından oluşturulan kök bağlamdan bağımsız olabilir.


Paylaştığın için teşekkürler dostum .. :)
Deepak Kumar

3

Servlet dosyanızı [servletname]-servlet.xmlaltında varsayılan adlandırma kuralı ve yolu yerine özel konumunuza veya özel adla koymak Web-INF/istediğinizde, kullanabilirsiniz ContextLoaderListener.


3

ContextLoaderListner, tüm farklı yapılandırma dosyalarını (hizmet katmanı yapılandırması, kalıcılık katmanı yapılandırması vb.) Tek yaylı uygulama bağlamına yükleyen bir Servlet dinleyicisidir.

Bu, yay yapılandırmalarını birden çok XML dosyasına bölmeye yardımcı olur.

Bağlam dosyaları yüklendikten sonra Spring, fasulye tanımına dayalı bir WebApplicationContext nesnesi oluşturur ve bunu web uygulamanızın ServletContext içinde depolar.


3

resim açıklamasını buraya girinBu Bootstrap dinleyicisi Spring'in kökünü başlatmak ve kapatmaktır WebApplicationContext'ini . Bir web uygulaması birden fazla dağıtıcı sunucu uygulamasına sahip olabilir ve her biri denetleyicileri, görünüm çözümleyiciyi, işleyici eşlemelerini vb. İçeren kendi uygulama içeriğine sahip olabilir. Ancak, hizmet fasulye, DAO fasulye kök uygulama bağlamında ve tüm alt uygulama bağlamında kullanmak isteyebilirsiniz ( dağıtıcı sunucu uygulamaları tarafından oluşturulan uygulama bağlamı).

Bu dinleyicinin 2. kullanımı, yay güvenliğini kullanmak istediğiniz zamandır.


3

Kök ve çocuk bağlamları Daha fazla okumadan önce lütfen şunu anlayın -

Bahar aynı anda birden fazla içeriğe sahip olabilir. Bunlardan biri kök bağlam olacak ve diğer tüm bağlamlar alt bağlam olacaktır.

Tüm alt bağlamlar kök bağlamda tanımlanan çekirdeklere erişebilir; ama tam tersi doğru değildir. Kök bağlam, alt bağlam çekirdeklerine erişemez.

ApplicationContext:

applicationContext.xml, her web uygulaması için kök içerik yapılandırmasıdır. Spring applicationContext.xml dosyasını yükler ve tüm uygulama için ApplicationContext'i oluşturur. Her bir web uygulaması için yalnızca bir uygulama içeriği olacaktır. ContextConfigLocation parametresini kullanarak web.xml dosyasında bağlam yapılandırma dosyası adını açıkça bildirmezseniz, Spring WEB-INF klasörü altında applicationContext.xml dosyasını arar ve bu dosyayı bulamazsa FileNotFoundException öğesini atar.

ContextLoaderListener Kök uygulama bağlamı için gerçek başlatma işini gerçekleştirir. Bir "contextConfigLocation" bağlam parametresini okur ve değerini bağlam örneğine iletir ve bunu, herhangi bir sayıda virgül ve boşlukla ayrılabilecek potansiyel olarak birden fazla dosya yoluna ayrıştırarak, örneğin “WEB-INF / applicationContext1.xml, WEB-INF / applicationContext2.xml”. ContextLoaderListener isteğe bağlıdır. Sadece burada bir noktaya değinmek için: Bir Spring uygulamasını ContextLoaderListener'ı yapılandırmadan, sadece temel bir minimum web.xml dosyası ile DispatcherServlet'i yapılandırmadan başlatabilirsiniz.

DispatcherServlet DispatcherServlet temel olarak yapılandırılmış URL modeliyle eşleşen gelen web isteklerini işlemek olan bir Servlet'dir (HttpServlet'i genişletir). Gelen bir URI alır ve doğru denetleyici ve görünüm kombinasyonunu bulur. Yani ön kontrolör.

Yay yapılandırmasında bir DispatcherServlet tanımladığınızda, contextConfigLocation özniteliğini kullanarak denetleyici sınıflarının girişlerini, görünüm eşlemelerini vb. İçeren bir XML dosyası sağlarsınız.

WebApplicationContext ApplicationContext dışında, tek bir web uygulamasında birden fazla WebApplicationContext olabilir. Basit bir deyişle, her bir DispatcherServlet tek bir WebApplicationContext ile ilişkilendirilir. xxx-servlet.xml dosyası DispatcherServlet'e özgüdür ve bir web uygulamasında istekleri işlemek için birden fazla DispatcherServlet yapılandırılmış olabilir. Bu tür senaryolarda, her DispatcherServlet'in ayrı bir xxx-servlet.xml yapılandırması olacaktır. Ancak, applicationContext.xml tüm sunucu uygulaması yapılandırma dosyaları için ortak olacaktır. Spring, varsayılan olarak webapps WEB-INF klasörünüzden “xxx-servlet.xml” adlı dosyayı yükler; burada xxx, web.xml içindeki sunucu uygulamasıdır. Bu dosya adının adını değiştirmek veya konumu değiştirmek isterseniz, contextConfigLocation ifadesine param adı olarak attempt-param ekleyin.

Karşılaştırma ve aralarındaki ilişki:

ContextLoaderListener vs DispatcherServlet

ContextLoaderListener kök uygulama içeriği oluşturur. DispatcherServlet girdileri, sunucu uygulaması girişi başına bir alt uygulama bağlamı oluşturur. Alt bağlamlar, kök bağlamda tanımlanan çekirdeklere erişebilir. Kök bağlamındaki fasulye, çocuk bağlamında (doğrudan) fasulyeye erişemez. Tüm bağlamlar ServletContext'e eklenir. Kök içeriğine WebApplicationContextUtils sınıfını kullanarak erişebilirsiniz.

İlkbahar dokümanlarını okuduktan sonra, anlayış şu şekildedir:

a) Uygulama Bağlamları hiyerarşiktir ve WebApplicationContexts de öyle. Buradaki belgelere bakın.

b) ContextLoaderListener, web uygulaması için bir kök web uygulaması bağlamı oluşturur ve bunu ServletContext'e yerleştirir. Bu bağlam, kontrolör katmanında (Struts veya Spring MVC) kullanılan teknolojiden bağımsız olarak, yay tarafından yönetilen fasulyeleri yüklemek ve boşaltmak için kullanılabilir.

c) DispatcherServlet kendi WebApplicationContext dosyasını oluşturur ve işleyiciler / denetleyiciler / görünüm çözümleyiciler bu bağlam tarafından yönetilir.

d) ContextLoaderListener, DispatcherServlet ile birlikte kullanıldığında, önce daha önce belirtildiği gibi bir kök web-uygulama-bağlamı oluşturulur ve DispatcherSerlvet tarafından bir alt-bağlam da oluşturulur ve kök uygulama bağlamına eklenir. Buradaki belgelere bakın.

Spring MVC ile çalıştığımızda ve hizmetler katmanında da Spring kullandığımızda, iki uygulama bağlamı sağlıyoruz. İlki ContextLoaderListener, diğeri DispatcherServlet ile yapılandırıldı

Genel olarak, MVC ile ilgili tüm çekirdekleri (kontrolör ve görünümler vb.) DispatcherServlet bağlamında ve güvenlik, işlem, hizmetler vb. Gibi tüm kesişen çekirdekleri ContextLoaderListener tarafından kök bağlamda tanımlayacaksınız.

Daha fazla ayrıntı için buna bakın: https://siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html


2

Temel olarak, ContextLoaderListner kullanarak kök uygulama içeriğinizi ve web uygulaması içeriğinizi izole edebilirsiniz.

Bağlam parametresi ile eşlenen yapılandırma dosyası, kök uygulama bağlamı yapılandırması gibi davranacaktır. Dağıtım programı sunucu uygulamasıyla eşlenen yapılandırma dosyası web uygulaması bağlamı gibi davranacaktır.

Herhangi bir web uygulamasında birden çok dağıtım programı sunucu uygulamasına sahip olabiliriz, bu nedenle birden çok web uygulaması bağlamı olabilir.

Ancak herhangi bir web uygulamasında, tüm web uygulaması bağlamlarıyla paylaşılan tek bir kök uygulama içeriğine sahip olabiliriz.

Ortak hizmetlerimizi, varlıkları, yönleri vb. Kök uygulama bağlamında tanımlamalıyız. Ve kontrolörler, önleyiciler vb ilgili web uygulaması bağlamındadır.

Örnek bir web.xml dosyası

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

Burada config sınıfı example.config.AppConfig, diğer tüm web uygulaması bağlamlarıyla paylaşılacak hizmetleri, varlıkları, yönleri vb. Kök uygulama bağlamında yapılandırmak için kullanılabilir (örneğin, burada iki web uygulaması bağlamı yapılandırma sınıfımız vardır RestConfig ve WebConfig)

Not: Burada ContextLoaderListener tamamen isteğe bağlıdır. Web.xml dosyasındaki ContextLoaderListener'dan bahsetmezsek, AppConfig çalışmaz. Bu durumda, WebConfig ve Rest Config içindeki tüm hizmetlerimizi ve varlıkları yapılandırmamız gerekir.


1

Web uygulaması dağıtım zamanında yürütülmesini istediğiniz bazı kodları koymak için kanca noktası verecektir


Jigar, aslında bu ne bulmaya çalışıyorum.Özellik nedir, varsayılan bağlam yükleyici sınıfı dağıtım zamanında sağlar?
M Sach

Özellikleri / xml dosyalarını değiştirme ve sunucuyu yeniden başlatmadan çalışma zamanında yeniden yüklenmelerine izin verme
vsingh

1

Dinleyici sınıfı - Bir etkinliği dinler (Örn. Sunucu başlatma / kapatma)

ContextLoaderListener -

  1. Sunucu başlatma / kapatma sırasında dinler
  2. Spring konfigürasyon dosyalarını girdi olarak alır ve konfigürasyona göre fasulyeleri oluşturur ve hazır hale getirir (kapatma sırasında fasulyeyi yok eder)
  3. Yapılandırma dosyaları web.xml dosyasında bunun gibi sağlanabilir

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

1

ContextLoaderListener'ın bahar çerçevesi bağlamında, uygulamanızın arka ucunu çalıştıran orta katman ve veri katmanı bileşenleri gibi diğer çekirdekleri de uygulamanıza yüklemektir.


0

Anlayışınız doğru. ContextLoaderListener'da neden herhangi bir avantaj görmediğinizi merak ediyorum. Örneğin, bir oturum fabrikası oluşturmanız gerekir (veritabanını yönetmek için). Bu işlem biraz zaman alabilir, bu nedenle başlangıçta yapmak daha iyidir. Elbette init sunucu uygulamaları ya da başka bir şeyle yapabilirsiniz, ancak Spring'in yaklaşımının avantajı, kod yazmadan yapılandırma yapmanızdır.


0

ContextLoaderListener olmadan web.xml yazarsak, bahar güvenliğinde customAuthenticationProvider kullanarak athuntication veremeyiz. DispatcherServelet, ContextLoaderListener öğesinin alt bağlamı olduğundan customAuthenticationProvider, parentContext öğesinin ContextLoaderListener olan parçasıdır. Dolayısıyla, üst Bağlam alt bağlamın bağımlılıklarına sahip olamaz. Bu yüzden initparam içine yazmak yerine spring-context.xml dosyasını contextparam'de yazmak en iyi uygulamadır.


0

Birden fazla yapılandırma dosyasına sahip olduğunuzda veya örneğin applicationcontext.xml yerine xyz.xml dosyanız olduğunda gerçek kullanımının geldiğine inanıyorum.

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

ContextLoaderListener için başka bir yaklaşım ContextLoaderServlet'i aşağıdaki gibi kullanmaktır

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.