Sự khác biệt giữa applicationContext.xml và spring-servlet.xml trong Spring Framework


373
  • Đang applicationContext.xmlspring-servlet.xmlliên quan dù sao đi nữa trong Spring Framework?
  • Các tập tin thuộc tính applicationContext.xmlsẽ được khai báo là có sẵn DispatcherServlet?
  • Trên một lưu ý liên quan, tại sao tôi cần một *-servlet.xmlchút? Tại sao applicationContext.xmlmột mình là không đủ?

1
Xem điều này là tốt. stackoverflow.com/questions/11708967/
Mạnh

Câu trả lời:


430

Spring cho phép bạn xác định nhiều bối cảnh trong hệ thống phân cấp cha-con.

Các applicationContext.xmlđịnh nghĩa đậu cho "bối cảnh webapp gốc", tức là bối cảnh liên quan đến ứng dụng web.

Các spring-servlet.xml(hoặc bất cứ điều gì khác mà bạn gọi nó) xác định đậu cho bối cảnh ứng dụng một servlet của. Có thể có nhiều trong số này trong một ứng dụng web, một cho mỗi servlet mùa xuân (ví dụ spring1-servlet.xmlcho servlet spring1, spring2-servlet.xmlcho servlet spring2).

Đậu trong spring-servlet.xmlcó thể tham khảo đậu trong applicationContext.xml, nhưng không phải ngược lại.

Tất cả các bộ điều khiển MVC của Spring phải đi trong spring-servlet.xmlngữ cảnh.

Trong hầu hết các trường hợp đơn giản, applicationContext.xmlbối cảnh là không cần thiết. Nó thường được sử dụng để chứa các hạt được chia sẻ giữa tất cả các máy chủ trong một ứng dụng web. Nếu bạn chỉ có một servlet, thì thực sự không có nhiều điểm, trừ khi bạn có một mục đích sử dụng cụ thể cho nó.


30
Tại sao bạn có nhiều lò xo mùa xuân?
NimChimpsky

5
câu trả lời mạnh mẽ (vì cô đọng)
lưỡng cư

35
@NimChimpsky đôi khi rất hữu ích khi tách các phần trong ứng dụng của bạn có thể xung đột trong cùng một bối cảnh. Ví dụ: bạn có thể có các dịch vụ ReST và chế độ xem chuẩn, sau đó bạn có thể có các trình giải quyết chế độ xem khác nhau hoặc mối quan tâm bảo mật cho các dịch vụ đối với các chế độ xem.
Brett Ryan

12
Mọi người nên xem câu trả lời này trước khi đọc tài liệu và phát triển ứng dụng! Trong các trường hợp bình thường, không cần phải có ContextLoaderListener và bối cảnhConfigLocation, chỉ cần DispatcherServlet!
ruruskyi

24
Trong nhiều hướng dẫn, bối cảnh bối cảnh có chứa distatcher-servlet.xml cũng như DispatcherServlet. Điều này khiến đậu được khởi tạo hai lần!
ruruskyi

106

cảnh 1

Trong ứng dụng khách (ứng dụng không phải là ứng dụng web, ví dụ: có thể là ứng dụng swing)

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

context.getBean(name);

Không cần web.xml . ApplicationContext như container để nhận dịch vụ bean. Không cần container máy chủ web. Trong test-client.xml có thể có Bean đơn giản mà không cần điều khiển từ xa, bean với điều khiển từ xa.

Kết luận : Trong kịch bản 1 applicationContext và DispatcherServletkhông liên quan.

Kịch bản 2

Trong một ứng dụng máy chủ (ứng dụng được triển khai trong máy chủ, ví dụ Tomcat). Dịch vụ được truy cập thông qua điều khiển từ xa từ chương trình máy khách (ví dụ: ứng dụng Swing)

Xác định trình nghe trong web.xml

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

Tại máy chủ khởi động, khởi ContextLoaderListenertạo các bean được định nghĩa trong applicationContext.xml .

Giả sử bạn đã định nghĩa các mục sau trong applicationContext.xml :

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

Các bean được khởi tạo từ tất cả bốn tệp cấu hình test1.xml , test2.xml , test3.xml , test4.xml .

Kết luận : Trong ứng dụng Kịch bản 2 Nội dung và DispatcherServletkhông liên quan.

Kịch bản 3

Trong một ứng dụng web với MVC mùa xuân.

Trong tệp web.xml xác định:

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

Khi Tomcat bắt đầu, các bean được định nghĩa trong springweb-servlet.xml được khởi tạo. DispatcherServletkéo dài FrameworkServlet. TrongFrameworkServlet khởi tạo đậu diễn ra cho springweb. Trong trường hợp của chúng tôi springweb là FrameworkServlet.

Phần kết luận : Trong kịch bản 3 ứng dụng Nội dung và DispatcherServletkhông liên quan.

Kịch bản 4

Trong ứng dụng web với MVC mùa xuân. springweb-servlet.xml cho servlet và applicationContext.xml để truy cập dịch vụ nghiệp vụ trong chương trình máy chủ hoặc để truy cập dịch vụ DB trong chương trình máy chủ khác.

Trong tệp web.xml, các mục sau được định nghĩa:

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

Khi khởi động máy chủ, ContextLoaderListenerkhởi tạo các bean được định nghĩa trong applicationContext.xml ; giả sử bạn đã tuyên bố ở đây:

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

Tất cả các bean được khởi tạo từ tất cả bốn test1.xml , test2.xml , test3.xml , test4.xml . Sau khi hoàn thành khởi tạo bean được định nghĩa trong applicationContext.xml , các bean được định nghĩa trong springweb-servlet.xml được khởi tạo.

Vì vậy, thứ tự khởi tạo là: root (bối cảnh ứng dụng), sau đó là FrameworkServlet.

Bây giờ cần phải rõ ràng tại sao chúng quan trọng trong kịch bản nào.


10
+1. Rất tốt. Tôi đã tìm kiếm loại so sánh này, nhưng không bao giờ tìm thấy.
Ninad Pingale

@abishkar Bhattarai rất tốt, câu hỏi của tôi là: như vậy là gì nếu sử dụng @ Component và @ Value chú thích để tạo ra đậu khi "Kịch bản 4"
lawrence

springweb DispatcherServletsẽ không được gọi nếu url không kết thúc bằng .action?
Asif Mushtaq

@lawrence Bạn vẫn sẽ phải chỉ định đường dẫn lớp trong springweb-servlet.xml để Spring có thể tìm thấy thành phần đó trong quá trình quét của nó.
veritas

54

Một điểm nữa tôi muốn thêm. Trong spring-servlet.xmlchúng tôi bao gồm quét thành phần cho gói Bộ điều khiển. Trong ví dụ sau, chúng tôi bao gồm chú thích bộ lọc cho gói bộ điều khiển.

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

Trong applicationcontext.xmlchúng tôi thêm bộ lọc cho gói còn lại không bao gồm bộ điều khiển.

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

9
tại sao ? Tại sao không chỉ quét toàn bộ một lần?
NimChimpsky

3
@NimChimpsky Bạn phải quét các @Controllerbean trong ngữ cảnh servlet (được yêu cầu bởi Spring MVC).
Tuukka Mustonen

3
Tại sao không thể toàn bộ điều hai lần? Tại sao bao gồm / loại trừ?
Mike Rylander

8
Người ta cũng nên thêm thuộc tính use-default-
tests

4
Rakesh Waghela có điểm. Nếu không có thuộc tính đó, bộ điều khiển sẽ được tạo hai lần. Thứ nhất là trong appContext và thứ hai là trong servletContext
UltraMaster

12

Nói một cách đơn giản,

applicationContext.xmlđịnh nghĩa các hạt được chia sẻ giữa tất cả các servlet. Nếu ứng dụng của bạn có nhiều hơn một servlet, thì việc xác định các tài nguyên chung trong applicationContext.xmlsẽ có ý nghĩa hơn.

spring-servlet.xmlđịnh nghĩa các bean chỉ liên quan đến servlet đó. Đây là servlet điều phối. Vì vậy, bộ điều khiển Spring MVC của bạn phải được xác định trong tệp này.

Không có gì sai khi định nghĩa tất cả các bean trong spring-servlet.xmlnếu bạn chỉ chạy một servlet trong ứng dụng web của mình.


3
Tôi có thể định nghĩa tất cả các bean trong spring-servlet.xml, nhưng cũng nên có applicationContext.xml có thể trống (không có bean) trong trường hợp này. Chính xác?
Mikhail Kopylov

6

Trong công nghệ Servlet nếu bạn muốn chuyển bất kỳ đầu vào nào cho một servlet cụ thể thì bạn cần truyền vào init param như mã bên dưới.

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

Nếu bạn muốn vượt qua một số thứ được đặt chung cho tất cả các máy chủ thì thời gian đó bạn cần phải cấu hình param param. Thí dụ

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

SO chính xác như thế này khi chúng tôi làm việc với Spring MVC, chúng tôi cần cung cấp một số thông tin cho servlet được xác định trước do Spring cung cấp, đó là DispatcherServlet thông qua init param. Vì vậy, cấu hình là như một số ít, ở đây chúng tôi đang cung cấp spring-servlet.xml làm tham số init cho 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>

Một lần nữa chúng ta cần một số thông số bối cảnh. Đó là áp dụng cho toàn bộ ứng dụng. Vì vậy, chúng tôi có thể cung cấp bối cảnh gốc là applicationcontext.xml Cấu hình như thế này:

    <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

Các bối cảnh ứng dụng cung cấp một phương tiện để giải quyết các tin nhắn văn bản, bao gồm hỗ trợ cho i18n của các tin nhắn đó. Các bối cảnh ứng dụng cung cấp một cách chung để tải tài nguyên tệp, chẳng hạn như hình ảnh. Bối cảnh ứng dụng có thể xuất bản các sự kiện cho các loại đậu được đăng ký làm người nghe. Một số thao tác trên container hoặc đậu trong container, phải được xử lý theo kiểu lập trình với nhà máy đậu, có thể được xử lý khai báo trong ngữ cảnh ứng dụng. Hỗ trợ ResourceLoader: Giao diện tài nguyên của Spring cho chúng ta một bản tóm tắt chung linh hoạt để xử lý các tài nguyên cấp thấp. Bản thân bối cảnh ứng dụng là ResourceLoader, do đó cung cấp cho ứng dụng quyền truy cập vào các phiên bản Tài nguyên dành riêng cho triển khai. Hỗ trợ MessageSource: Bối cảnh ứng dụng triển khai MessageSource, giao diện được sử dụng để lấy các tin nhắn được bản địa hóa,

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.