ความแตกต่างระหว่าง applicationContext.xml และ spring-servlet.xml ใน Spring Framework


373
  • มีapplicationContext.xmlและspring-servlet.xmlที่เกี่ยวข้อง แต่อย่างใดในฤดูใบไม้ผลิกรอบ?
  • ไฟล์คุณสมบัติที่ประกาศapplicationContext.xmlใช้จะพร้อมใช้งานDispatcherServletหรือไม่
  • ในบันทึกที่เกี่ยวข้องทำไมฉันต้องมี*-servlet.xmlเลย? ทำไมapplicationContext.xmlคนเดียวไม่เพียงพอ?

1
ดูสิ่งนี้เช่นกัน stackoverflow.com/questions/11708967/…
Sanghyun Lee

คำตอบ:


430

Spring ให้คุณกำหนดหลายบริบทในลำดับชั้นของผู้ปกครองเด็ก

การapplicationContext.xmlกำหนดถั่วสำหรับ "รูทบริบทเว็บแอป" คือบริบทที่เกี่ยวข้องกับเว็บแอป

spring-servlet.xml(หรือสิ่งอื่นที่คุณเรียกว่า) กำหนดถั่วบริบทหนึ่ง app ของ servlet สามารถมีได้หลายเหล่านี้ใน webapp หนึ่งต่อฤดูใบไม้ผลิเซิร์ฟเล็ต (เช่นspring1-servlet.xmlสำหรับเซิร์ฟเล็ตspring1, spring2-servlet.xmlสำหรับเซิร์ฟเล็ตspring2)

ถั่วในspring-servlet.xmlสามารถอ้างอิงถั่วในapplicationContext.xmlแต่ไม่ใช่ในทางกลับกัน

Spring MVC คอนโทรลเลอร์ทั้งหมดต้องดำเนินการตามspring-servlet.xmlบริบท

ในกรณีส่วนใหญ่applicationContext.xmlบริบทไม่จำเป็น โดยทั่วไปจะใช้เพื่อมีถั่วที่ใช้ร่วมกันระหว่าง servlets ทั้งหมดใน webapp ถ้าคุณมี servlet เพียงอันเดียวก็ไม่ได้มีจุดมากนักเว้นแต่ว่าคุณจะใช้มันโดยเฉพาะ


30
ทำไมคุณถึงมีสปริงหลายแห่ง
NimChimpsky

5
คำตอบที่ทรงพลัง (เพราะความรัดกุม)
สัตว์สะเทินน้ำสะเทินบก

35
@NimChimpsky บางครั้งมีประโยชน์ในการแยกส่วนของแอปพลิเคชันของคุณที่อาจขัดแย้งกันในบริบทเดียวกัน ตัวอย่างเช่นคุณอาจมีบริการ ReST และมุมมองมาตรฐานจากนั้นคุณอาจมีตัวแก้ไขมุมมองหรือข้อกังวลด้านความปลอดภัยที่แตกต่างกันสำหรับบริการเกี่ยวกับมุมมอง
Brett Ryan

12
ผู้คนควรเห็นคำตอบนี้ก่อนอ่านเอกสารและพัฒนาแอพ! ในกรณีปกติไม่จำเป็นต้องมี ContextLoaderListener และ contextConfigLocation เลยเพียง DispatcherServlet!
ruruskyi

24
ในบทเรียนมากมาย contextConfigLocation มี dispatcher-servlet.xml เช่นเดียวกับ DispatcherServlet นี่ทำให้ถั่วเริ่มต้นสองครั้ง!
ruruskyi

106

สถานการณ์ 1

ในแอปพลิเคชันไคลเอนต์ (แอปพลิเคชันไม่ใช่เว็บแอปพลิเคชันเช่นอาจเป็นแอปพลิเคชันแบบแกว่ง)

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

context.getBean(name);

ไม่จำเป็นต้องweb.xml ApplicationContext เป็นคอนเทนเนอร์สำหรับรับบริการ bean ไม่จำเป็นต้องมีเว็บเซิร์ฟเวอร์คอนเทนเนอร์ ในtest-client.xmlสามารถมี Simple bean โดยไม่มี remoting, bean พร้อม remoting

สรุป : ในสถานการณ์สมมติ 1 applicationContext และDispatcherServletไม่เกี่ยวข้อง

สถานการณ์ที่ 2

ในแอปพลิเคชันเซิร์ฟเวอร์ (แอปพลิเคชันที่ปรับใช้ในเซิร์ฟเวอร์เช่น Tomcat) เข้าถึงบริการผ่าน remoting จากโปรแกรมไคลเอนต์ (เช่น Swing app)

กำหนดฟังในweb.xml

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

ที่เซิร์ฟเวอร์เริ่มต้นContextLoaderListenerinstantiates ถั่วที่กำหนดไว้ในapplicationContext.xml

สมมติว่าคุณได้กำหนดสิ่งต่อไปนี้ในapplicationContext.xml :

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

ถั่ว instantiated จากทั้งสี่แฟ้มการกำหนดค่าtest1.xml , test2.xml , test3.xml , test4.xml

สรุป : ในสถานการณ์สมมติ 2 applicationContext และ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 เริ่มทำงาน bean ที่กำหนดในspringweb-servlet.xmlจะถูกสร้างอินสแตนซ์ ขยายDispatcherServlet FrameworkServletในการFrameworkServletสร้างอินสแตนซ์ของถั่วจะเกิดขึ้นสำหรับสปริงเว็บ ในกรณีของเราสปริงเว็บคือ FrameworkServlet

สรุป : ในสถานการณ์สมมติ 3 applicationContext และDispatcherServletไม่เกี่ยวข้อง

สถานการณ์ 4

ในเว็บแอปพลิเคชันด้วย spring MVC springweb-servlet.xmlสำหรับ servlet และapplicationContext.xmlสำหรับการเข้าถึงบริการธุรกิจภายในโปรแกรมเซิร์ฟเวอร์หรือสำหรับการเข้าถึงบริการ DB ในโปรแกรมเซิร์ฟเวอร์อื่น

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

เมื่อเริ่มต้นเซิร์ฟเวอร์ContextLoaderListenerinstantiates ถั่วที่กำหนดไว้ใน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 ทั้งสี่ หลังจากการสร้างอินสแตนซ์ของ bean ที่กำหนดในapplicationContext.xmlเสร็จสมบูรณ์ bean ที่กำหนดในspringweb-servlet.xmlจะถูกสร้างอินสแตนซ์

ดังนั้นอินสแตนซ์ของคำสั่งคือ: รูท (บริบทของแอ็พพลิเคชัน), จากนั้น FrameworkServlet

ตอนนี้มันควรจะชัดเจนว่าทำไมพวกเขาถึงมีความสำคัญในสถานการณ์


10
+1 ดีมากฉันกำลังมองหาการเปรียบเทียบประเภทนี้ แต่ไม่เคยพบ
Ninad Pingale

@abishkar bhattarai ดีมากคำถามของฉันคือ: แล้วจะเป็นอย่างไรถ้าใช้ @ Component และ @ Value หมายเหตุประกอบเพื่อสร้าง bean เมื่อ "Scenario 4"
lawrence

สปริงเวบDispatcherServletจะไม่เรียกถ้า URL ไม่ลงท้ายด้วย.
Asif Mushtaq

@ ลอเรนซ์คุณจะต้องระบุคลาสพา ธ ใน 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 คุณต้องสแกน@Controllerbeans ในบริบท servlet (ต้องการโดย Spring MVC)
Tuukka Mustonen

3
ทำไมทั้งสองสิ่งไม่สามารถทำได้? ทำไมรวม / ไม่รวม?
Mike Rylander

8
สิ่งหนึ่งที่ควรเพิ่ม attribute-default-filters = "false" ใน spring-servlet.xml
Rakesh Waghela

4
Rakesh Waghela มีประเด็น หากไม่มีแอตทริบิวต์นั้นก็จะสร้าง Controller beans สองครั้ง ประการแรกใน appContext และที่สองใน servletContext
UltraMaster

12

ในคำง่าย ๆ

applicationContext.xmlกำหนด beans ที่แบ่งใช้ระหว่างเซิร์ฟเล็ตทั้งหมด หากแอปพลิเคชันของคุณมีมากกว่าหนึ่งเซิร์ฟเล็ตให้กำหนดทรัพยากรทั่วไปในapplicationContext.xmlเหมาะสม

spring-servlet.xmlกำหนด beans ที่เกี่ยวข้องกับเซิร์ฟเล็ตนั้นเท่านั้น นี่คือ servlet ของดิสแพตเชอร์ ดังนั้นตัวควบคุม Spring MVC ของคุณจะต้องกำหนดไว้ในไฟล์นี้

ไม่มีอะไรผิดปกติในการกำหนด beans ทั้งหมดในspring-servlet.xmlหากคุณกำลังรันเซิร์ฟเล็ตเพียงหนึ่งเดียวในเว็บแอ็พพลิเคชันของคุณ


3
ฉันสามารถกำหนดถั่วทั้งหมดใน spring-servlet.xml แต่ก็ควรมี applicationContext.xml ที่อาจว่างเปล่า (ไม่มีถั่ว) ในกรณีนี้ แก้ไข?
Mikhail Kopylov

6

ในเทคโนโลยี Servlet หากคุณต้องการส่งผ่านอินพุตใด ๆ ไปยัง servlet เฉพาะคุณต้องผ่านพารามิเตอร์เริ่มต้นเช่นรหัสด้านล่าง

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

หากคุณต้องการส่งบางส่วนที่เป็นเรื่องธรรมดาสำหรับเซิร์ฟเล็ตทั้งหมดดังนั้นเวลาที่คุณต้องกำหนดค่าพารามิเตอร์บริบท ตัวอย่าง

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

ดังนั้นอย่างนี้เมื่อเราทำงานกับ Spring MVC เราจำเป็นต้องให้ข้อมูลบางอย่างแก่ servlet ที่กำหนดไว้ล่วงหน้าที่ให้บริการโดย 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 ของข้อความเหล่านั้น บริบทของแอปพลิเคชันให้วิธีการทั่วไปในการโหลดทรัพยากรไฟล์เช่นรูปภาพ บริบทของแอปพลิเคชันสามารถเผยแพร่กิจกรรมไปยัง beans ที่ลงทะเบียนเป็น listeners การดำเนินการบางอย่างบนภาชนะบรรจุหรือถั่วในภาชนะบรรจุซึ่งจะต้องได้รับการจัดการแบบเป็นโปรแกรมกับโรงงานถั่วสามารถจัดการได้อย่างชัดเจนในบริบทของแอปพลิเคชัน การสนับสนุน ResourceLoader: ส่วนต่อประสานทรัพยากรของ Spring ทำให้เราเป็นนามธรรมที่มีความยืดหยุ่นสำหรับการจัดการทรัพยากรระดับต่ำ บริบทของแอปพลิเคชันนั้นเป็น ResourceLoader ดังนั้นจึงจัดเตรียมแอปพลิเคชันที่สามารถเข้าถึงอินสแตนซ์ของทรัพยากรเฉพาะสำหรับการปรับใช้ รองรับ MessageSource: บริบทของแอปพลิเคชันใช้ MessageSource ซึ่งเป็นอินเตอร์เฟสที่ใช้เพื่อรับข้อความที่แปลแล้ว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.