Perbedaan antara applicationContext.xml dan spring-servlet.xml di Spring Framework

373
  • Apakah applicationContext.xmldan spring-servlet.xmlbagaimanapun terkait dalam Kerangka Kerja Spring?
  • Akankah file properti yang dideklarasikan applicationContext.xmltersedia untuk DispatcherServlet?
  • Pada catatan terkait, mengapa saya perlu *-servlet.xmlsama sekali? Mengapa applicationContext.xmlsendirian saja tidak cukup?
pengguna448070
sumber
1
Lihat ini juga. stackoverflow.com/questions/11708967/…
Sanghyun Lee

Jawaban:

430

Spring memungkinkan Anda mendefinisikan banyak konteks dalam hierarki orangtua-anak.

The applicationContext.xmlmendefinisikan kacang untuk "konteks webapp root", yaitu konteks yang terkait dengan webapp.

The spring-servlet.xml(atau apa pun yang Anda sebut) mendefinisikan kacang untuk konteks aplikasi satu servlet. Mungkin ada banyak dari ini di webapp, satu per Spring servlet (misalnya spring1-servlet.xmluntuk servlet spring1, spring2-servlet.xmluntuk servlet spring2).

Kacang dalam spring-servlet.xmldapat merujuk kacang dalam applicationContext.xml, tetapi tidak sebaliknya.

Semua pengendali Spring MVC harus masuk dalam spring-servlet.xmlkonteks.

Dalam kebanyakan kasus sederhana, applicationContext.xmlkonteksnya tidak perlu. Biasanya digunakan untuk mengandung kacang yang dibagikan di antara semua servlet di webapp. Jika Anda hanya memiliki satu servlet, maka tidak ada gunanya, kecuali Anda memiliki penggunaan khusus untuk itu.

skaffman
sumber
30
mengapa Anda memiliki beberapa servlets musim semi?
NimChimpsky
5
jawaban kuat yang perkasa (karena ringkasnya)
amfibi
35
@NimChimpsky terkadang berguna untuk memisahkan bagian-bagian dari aplikasi Anda yang dapat bertentangan dalam konteks yang sama. Sebagai contoh, Anda mungkin memiliki layanan REST dan tampilan standar, maka Anda mungkin memiliki resolusi tampilan yang berbeda atau masalah keamanan untuk layanan seperti pandangan.
Brett Ryan
12
Orang-orang harus melihat jawaban ini sebelum membaca dokumentasi dan mengembangkan aplikasi! Dalam kasus normal tidak perlu memiliki ContextLoaderListener dan contextConfigLocation sama sekali, cukup DispatcherServlet!
ruruskyi
24
Dalam banyak tutorial, contextConfigLocation berisi dispatcher-servlet.xml dan juga DispatcherServlet. Ini menyebabkan kacang diinisialisasi dua kali!
ruruskyi
106

skenario 1

Dalam aplikasi klien (aplikasi bukan aplikasi web, mis. Mungkin aplikasi ayun)

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

context.getBean(name);

Tidak perlu web.xml . ApplicationContext sebagai wadah untuk mendapatkan layanan kacang. Tidak perlu wadah server web. Di test-client.xml mungkin ada kacang Sederhana tanpa remoting, kacang dengan remoting.

Kesimpulan : Dalam Konteks 1 aplikasiContext dan DispatcherServlettidak terkait.

Skenario 2

Dalam aplikasi server (aplikasi yang digunakan di server misalnya Tomcat). Layanan yang diakses melalui remoting dari program klien (misalnya aplikasi Swing)

Tentukan pendengar di web.xml

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

Di server, startup ContextLoaderListenerinstantiates beans didefinisikan dalam applicationContext.xml .

Dengan asumsi Anda telah menentukan yang berikut ini di applicationContext.xml :

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

Kacang yang instantiated dari keempat file konfigurasi test1.xml , test2.xml , test3.xml , test4.xml .

Kesimpulan : Dalam Konteks 2 aplikasiContext dan DispatcherServlettidak terkait.

Skenario 3

Dalam aplikasi web dengan pegas MVC.

Di web.xml define:

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

Ketika Tomcat dimulai, kacang yang didefinisikan dalam springweb-servlet.xml dipakai. DispatcherServletmeluas FrameworkServlet. Dalam FrameworkServletkacang Instansiasi berlangsung untuk springweb. Dalam kasus kami springweb adalah FrameworkServlet.

Kesimpulan : Dalam Konteks 3 applicationContext dan DispatcherServlettidak terkait.

Skenario 4

Dalam aplikasi web dengan pegas MVC. springweb-servlet.xml untuk servlet dan applicationContext.xml untuk mengakses layanan bisnis dalam program server atau untuk mengakses layanan DB di program server lain.

Di web.xml berikut ini didefinisikan:

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

Pada permulaan server, ContextLoaderListenerinstanti kacang yang ditentukan dalam applicationContext.xml ; dengan asumsi Anda telah menyatakan di sini:

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

Kacang semua instantiated dari keempat test1.xml , test2.xml , test3.xml , test4.xml . Setelah penyelesaian instantiasi kacang didefinisikan dalam applicationContext.xml , kacang didefinisikan dalam springweb-servlet.xml adalah instantiated.

Jadi urutan instantiasi adalah: root (konteks aplikasi), lalu FrameworkServlet.

Sekarang harus jelas mengapa mereka penting dalam skenario mana.

abishkar bhattarai
sumber
10
+1. Sangat bagus. Saya mencari jenis perbandingan ini, tetapi tidak pernah ditemukan.
Ninad Pingale
@abishkar bhattarai sangat bagus, pertanyaan saya adalah: jadi bagaimana jika menggunakan @ Component dan @ Value annotation untuk membuat bean ketika "Skenario 4"
lawrence
springweb DispatcherServlettidak akan dipanggil jika url tidak diakhiri dengan .action?
Asif Mushtaq
@ undang-undang Anda masih harus menentukan lintasan kelas di springweb-servlet.xml sehingga Spring dapat menemukan komponen itu dalam pemindaiannya.
veritas
54

Satu hal lagi yang ingin saya tambahkan. Dalam spring-servlet.xmlkami menyertakan pemindaian komponen untuk paket Kontroler. Dalam contoh berikut ini kami menyertakan anotasi filter untuk paket pengontrol.

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

Di applicationcontext.xmlkami tambahkan filter untuk paket yang tersisa tidak termasuk controller.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
Raje
sumber
9
kenapa Mengapa tidak memindai semuanya sekaligus?
NimChimpsky
3
@NimChimpsky Anda harus memindai @Controllerkacang dalam konteks servlet (diperlukan oleh Spring MVC).
Tuukka Mustonen
3
Kenapa tidak bisa semuanya dua kali? Mengapa menyertakan / mengecualikan?
Mike Rylander
8
Orang juga harus menambahkan atribut use-default-filter = "false" di spring-servlet.xml
Rakesh Waghela
4
Rakesh Waghela benar. Tanpa atribut kacang Controller akan dibuat dua kali. Pertama di appContext dan kedua di servletContext
UltraMaster
12

Dengan kata-kata sederhana,

applicationContext.xmlmendefinisikan kacang yang dibagikan di antara semua servlets. Jika aplikasi Anda memiliki lebih dari satu servlet, maka mendefinisikan sumber daya bersama di applicationContext.xmlakan lebih masuk akal.

spring-servlet.xmlmendefinisikan kacang yang hanya terkait dengan servlet itu. Ini dia servlet pengirim. Jadi, pengendali Spring MVC Anda harus ditentukan dalam file ini.

Tidak ada yang salah dalam mendefinisikan semua kacang di spring-servlet.xmljika Anda hanya menjalankan satu servlet di aplikasi web Anda.

Krishna
sumber
3
Saya bisa mendefinisikan semua kacang di spring-servlet.xml, tetapi juga harus ada applicationContext.xml yang mungkin kosong (tanpa kacang) dalam kasus ini. Benar?
Mikhail Kopylov
6

Dalam teknologi Servlet jika Anda ingin meneruskan input apa pun ke servlet tertentu, maka Anda harus memasukkan param init seperti kode di bawah ini.

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

Jika Anda ingin melewatkan beberapa di tempat yang umum untuk semua servlets maka saat itu Anda perlu mengkonfigurasi param konteks. Contoh

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

JADI persis seperti ini ketika kita bekerja dengan Spring MVC kita perlu memberikan beberapa informasi kepada servlet yang disediakan oleh Spring yaitu DispatcherServlet melalui init param. Jadi konfigurasinya adalah sebagai fallows, di sini kami menyediakan spring-servlet.xml sebagai parameter init untuk 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>

Sekali lagi kita memerlukan beberapa parameter konteks. Itu berlaku untuk seluruh aplikasi. Jadi kami dapat menyediakan konteks root yaitu applicationcontext.xml Konfigurasi seperti ini:

    <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>
Rajanikanta Pradhan
sumber
4

Konteks aplikasi menyediakan sarana untuk menyelesaikan pesan teks, termasuk dukungan untuk i18n dari pesan-pesan itu. Konteks aplikasi menyediakan cara umum untuk memuat sumber daya file, seperti gambar. Konteks aplikasi dapat mempublikasikan acara ke kacang yang terdaftar sebagai pendengar. Operasi tertentu pada wadah atau kacang dalam wadah, yang harus ditangani secara terprogram dengan pabrik kacang, dapat ditangani secara deklaratif dalam konteks aplikasi. Dukungan ResourceLoader: Spring's Resource interface kami abstraksi generik yang fleksibel untuk menangani sumber daya tingkat rendah. Konteks aplikasi itu sendiri adalah ResourceLoader, Oleh karena itu menyediakan aplikasi dengan akses ke instance Sumber Daya spesifik penyebaran. Dukungan MessageSource: Konteks aplikasi mengimplementasikan MessageSource, sebuah antarmuka yang digunakan untuk mendapatkan pesan lokal,

Sujata
sumber