ContextLoaderListener veya değil mi?


122

Standart bir yay web uygulaması (Roo veya "Spring MVC Project" Template tarafından oluşturulmuş) ContextLoaderListenerve ile bir web.xml oluşturur DispatcherServlet. Neden DispatcherServlettüm konfigürasyonu yüklemek için sadece kullanmıyorlar ve bunu yapmıyorlar ?

ContextLoaderListener'ın web ile ilgili olmayan şeyleri yüklemek için kullanılması gerektiğini ve DispatcherServlet'in web ile ilgili öğeleri yüklemek için kullanıldığını anlıyorum (Denetleyiciler, ...). Ve bu iki bağlamla sonuçlanır: bir ebeveyn ve bir alt bağlam.

Arka fon:

Birkaç yıldır bu standart şekilde yapıyordum.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Handles Spring requests -->
<servlet>
    <servlet-name>roo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/webmvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Bu genellikle iki bağlamda ve aralarındaki bağımlılıklarda sorunlara neden oldu. Geçmişte her zaman bir çözüm bulabildim ve bunun yazılım yapısını / mimarisini her zaman daha iyi hale getirdiğine dair güçlü bir his var. Ama şimdi her iki bağlamdaki olaylarla ilgili bir sorunla karşı karşıyayım .

- Ancak bu, bu iki bağlam kalıbını yeniden düşünmeme neden oluyor ve kendime soruyorum: neden kendimi bu belaya sokayım, neden tüm yay yapılandırma dosyalarını biriyle DispatcherServletyükleyip ContextLoaderListenertamamen kaldırmıyorum ? (Yine de farklı yapılandırma dosyalarına sahip olacağım, ancak yalnızca bir içeriğe sahip olacağım.)

Kaldırmamak için herhangi bir sebep var mı ContextLoaderListener?


"Bu genellikle iki bağlamda ve aralarındaki bağımlılıklarda sorunlara neden oldu." Bu, bağımlılık enjeksiyon çerçevelerinin hayatımızı kendin yap bağımlılık enjeksiyonundan daha zor hale getirdiğini düşündüğüm harika bir örnek.
Andy

1
@Andy - Bu bakış açısına biraz sempati duysam da, her iki bağlama da ihtiyaç duyduğunuz kullanım durumlarının farkına varmadan edemiyorum (nesneleri güvenlik filtreleri ve sunucu uygulamaları arasında paylaşma, işlemleri otomatik olarak yönetme, böylece görünümden sonra kapatılmışlar) yeniden yönlendirdiğiniz, işlemeyi bitirdi) çerçevenin yardımı olmadan elde etmek oldukça zordur. Bunun nedeni, servlet API'sinin hiçbir zaman bağımlılık enjeksiyonu ile çalışmak üzere tasarlanmamış olması ve bunu kendiniz yapmaya çalışırsanız aktif olarak size karşı çalışmasıdır.
Periata Breatta

@PeriataBreatta Görüyorum! Peki, farklı tasarlanmış olsaydı, Spring MVC'ye daha iyi alternatifler olacağını düşünüyor musunuz? Yine de insanlar Servlet API'ye tam alternatifler tasarlayabilirlerdi ...
Andy

@PeriataBreatta Bir yıldır HTTP isteklerini yönlendirmek için Express'i kullandığım JS dünyasında, "bağımlılık enjeksiyonu" ndan nadiren bahsedildiğini ve Spring çerçevesine hiç benzeyen hiçbir şey görmüyorum.
Andy

Yanıtlar:


86

Senin durumunda, hayır, tutmak için hiçbir neden yok ContextLoaderListenerve applicationContext.xml. Uygulamanız yalnızca sunucu uygulamasının bağlamıyla iyi çalışıyorsa, buna bağlı kalırsa, daha basittir.

Evet, genel olarak teşvik edilen model, web olmayan şeyleri web uygulaması düzeyinde bağlamda tutmaktır, ancak bu zayıf bir kuraldan başka bir şey değildir.

Web uygulaması düzeyinde bağlamı kullanmanın tek zorlayıcı nedenleri şunlardır:

  • DispatcherServletHizmetleri paylaşmanız gereken birden çok cihazınız varsa
  • Spring kablolu hizmetlere erişmesi gereken eski / Spring olmayan sunucu uygulamalarınız varsa
  • Eğer servlet filtreleri varsa o Webapp düzey bağlamında içine kanca (örn Bahar Güvenlik Kullanıcı DelegatingFilterProxy, OpenEntityManagerInViewFiltervs.)

Bunların hiçbiri sizin için geçerli değildir, bu yüzden ekstra karmaşıklık haksızdır.

Vb zamanlanmış görevler, JMS bağlantıları gibi, servlet'in bağlamına arka plan görevleri eklerken eklemek unutursanız Sadece dikkatli olun <load-on-startup>adresinden Müşteri web.xml, daha sonra bu görevler servlet'ten ilk erişimine kadar başlamış edilmeyecektir.


2
Peki dinleyiciler, Context Loader dinleyicisine göre oluşturulan Context'e ihtiyaç duyduklarını anlıyor (IllegalStateException, No WebApplicationContext bulunamadı, MultipartFilter, CharacterEncodingFilter, HiddenHttpMethodFilter, Spring Security DelegatingFilterProxy ve OpenEntityManagerInViewFilter tarafından tetiklenen). Tersi bir şekilde yapmak iyi bir fikir mi (Her şeyi ContextLoaderListener ile yükleyin ve DispatcherServlet'i bir konfigürasyon olmadan bırakın)?
Ralph

@Ralph: İyi yakaladım, bu kullanım durumunu listeye ekledim. DispatcherServletKonfigürasyon olmadan ayrılma konusuna gelince - bunu yaparsanız, web arayüzünüz olmazdı. Tüm MVC malzemeleri oraya girmeli.
skaffman

2
@skaffman DelegatingFilterProxy ile yay güvenliğini kullanırken neden iki bağlam kullanmalıyım? Benim durumumda yay güvenlikli çekirdekler ve varsayılan yay bağlamı bazı fasulyeleri paylaşır. Dolayısıyla aynı bağlamı paylaşmaları gerekir. Yoksa yaylı güvenlik çekirdekleri varsayılan yay bağlamının dışında mı tutulmalı?
Matthias M

10

Uygulama bağlamını başka bir şekilde de yapılandırabilirsiniz. Örneğin, OpenEntityManagerInViewFilter'ın çalışmasını sağlamak için . Kur ContextLoaderListener ve ardından DispatcherServlet ile yapılandırın:

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
</servlet>

Sadece contextConfigLocation parametre değerinin boş olduğundan emin olun .


1
Peki bu konfigürasyonun avantajı nedir? Ve "tam tersi" ile ne demek istiyorsun?
Ralph

"Skaffman" tarafından sunulan çözüm, yalnızca bir web uygulaması bağlamı (sunucu uygulaması) yapılandırdı. Bununla birlikte, bu yaklaşımla, çözümün kendisinde ayrıntılı olarak açıklanan sorunlarla karşılaşırsınız: "Webapp düzeyinde bağlamı kullanmak için tek zorlayıcı nedenler şunlardır:" ... "Webbapp düzeyinde içeriğe (ör. Spring Security'nin DelegatingFilterProxy, OpenEntityManagerInViewFilter, vb.) "Yalnızca 1 uygulama bağlamı XML dosyası kullanmak isterseniz, benim çözümümün (XML'i ContextLoaderListener aracılığıyla belirtilmesi) tercih edileceğini düşünüyorum.
Gunnar Hillert

Context Listener tarafından oluşturulan Context içinde MVC Web Controller'ı kullanabiliyor musunuz?
Ralph

1
Evet. Denetleyicilerinizi Context Listener tarafından belirtilen context.xml dosyasında kurmanız yeterlidir. Bunun çalışma şekli, DispatcherServlet'in "ana uygulama bağlamına" (Bağlam Dinleyici) katılmasıdır. "ContextConfigLocation" değerini boş bıraktığınızda, Context Listener tarafından belirtilen context.xml dosyası özel olarak kullanılacaktır.
Gunnar Hillert

1
Sanırım bağlamınızda <mvc: annotation-drive /> özlediniz. @GunnarHillert çözümü benim için çalışıyor.
milbr

10

Spring-MVC uygulamamda yaptıklarımı paylaşmak istiyorum:

  1. On we-mvc-config.xmlBen @Controller ile açıklamalı sadece sınıfları ekledi:

    <context:component-scan base-package="com.shunra.vcat">
        <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    </context:component-scan>
  2. Geri applicationContext.xmlkalan her şeyi ekledim dosyalara:

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

Evet, bu kullanışlı bir model. Diğer bir kullanışlı model de, veri tabanı işleme fasulyelerinizi uygulama bağlamına (bunlar muhtemelen bir OpenSessionInViewFilter veya benzeri için gereklidir), filtreler veya dinleyiciler tarafından özel olarak ihtiyaç duyulan herhangi bir şeyle (örneğin, yay güvenliğini kullanmak için gerekli tanımlar) yerleştirmektir.
Periata Breatta
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.