Dispatcher Servlet trong mùa xuân là gì?


195

Trong hình ảnh này (mà tôi nhận được từ đây ), yêu cầu HTTP sẽ gửi một cái gì đó đến Dispatcher Servlet.

nhập mô tả hình ảnh ở đây

Câu hỏi của tôi là Dispatcher Servlet làm gì?

Có phải nó giống như lấy thông tin từ trang web và ném đến bộ điều khiển không?

Câu trả lời:


202

Công việc của DispatcherServlet là lấy một URI đến và tìm ra sự kết hợp đúng của các trình xử lý (nói chung là các phương thức trên các lớp Trình điều khiển ) và các khung nhìn (nói chung là các tệp JSP) kết hợp để tạo ra trang hoặc tài nguyên được cho là tìm thấy tại vị trí đó.

Tôi có thể có

  • một tập tin /WEB-INF/jsp/pages/Home.jsp
  • và một phương thức trên một lớp

    @RequestMapping(value="/pages/Home.html")
    private ModelMap buildHome() {
        return somestuff;
    }

Các servlet Dispatcher là bit rằng "biết" để gọi phương thức rằng khi một trình duyệt yêu cầu trang, và để kết hợp kết quả của nó với các hợp tập tin JSP để tạo một tài liệu html.

Làm thế nào nó thực hiện điều này rất khác nhau với cấu hình và phiên bản Spring.

Không có lý do gì kết quả cuối cùng phải là các trang web. Nó có thể làm điều tương tự để xác định vị trí các điểm cuối RMI , xử lý các yêu cầu SOAP , bất cứ điều gì có thể đi vào một servlet.


4
Riposte tuyệt vời, bây giờ một câu hỏi làm thế nào mà DispatcherServlet xác định tên lớp và tên phương thức. Bạn có thể chỉ cho tôi một ví dụ về cấu hình trong đó tôi có hai lớp và hai tên phương thức không và làm thế nào để DispatcherServlet nắm bắt đúng yêu cầu.
Kevin

10
Nó thực sự quét đường dẫn lớp khi khởi động cho chú thích đó và tạo ánh xạ của "/pages/Home.html" sang Phương thức Class +. Nếu bạn có hai phương thức mà cả hai đều có "/pages/Home.html" mà không có hạn chế nào khác trong chú thích của chúng, đó sẽ là một lỗi và nó sẽ ném ngoại lệ cho bạn. Bạn cũng có thể kết nối nó với XML nếu bạn học cũ.
Ảnh hưởng

2
Chúng ta có cần một Dispatcher Servlettệp xml khi sử dụng Chú thích Dựa @RestControllerkhông?
viper

1
@viper trong web.xml, chúng tôi luôn cần định cấu hình servlet bộ điều phối mặc dù bạn sử dụng chú thích hoặc cấu hình xml
Mahender Reddy Yasa

Có loại nào khác của servlet không?
Minh Nghĩa

72

Trong Spring MVC, tất cả các yêu cầu đến đều đi qua một servlet. Servlet này - DispatcherServlet- là bộ điều khiển phía trước. Bộ điều khiển phía trước là một mẫu thiết kế điển hình trong phát triển ứng dụng web. Trong trường hợp này, một servlet duy nhất nhận được tất cả các yêu cầu và chuyển chúng đến tất cả các thành phần khác của ứng dụng.

Nhiệm vụ của DispatcherServletlà gửi yêu cầu đến bộ điều khiển Spring MVC cụ thể.

Thông thường chúng ta có rất nhiều bộ điều khiển và DispatcherServlettham khảo một trong những người lập bản đồ sau để xác định bộ điều khiển đích:

Nếu không có cấu hình được thực hiện, việc DispatcherServletsử dụng BeanNameUrlHandlerMappingDefaultAnnotationHandlerMappingtheo mặc định.

Khi bộ điều khiển đích được xác định, DispatcherServletyêu cầu gửi đến nó. Bộ điều khiển thực hiện một số công việc theo yêu cầu (hoặc ủy thác nó cho các đối tượng khác) và quay trở lại DispatcherServletvới Mô hình và tên của Chế độ xem.

Tên của Chế độ xem chỉ là một tên hợp lý. Tên logic này sau đó được sử dụng để tìm kiếm Chế độ xem thực tế (để tránh khớp với bộ điều khiển và Chế độ xem cụ thể). Sau đó DispatcherServletđề cập đến ViewResolvervà ánh xạ tên logic của Chế độ xem sang triển khai cụ thể của Chế độ xem.

Một số triển khai có thể có ViewResolverlà:

Khi DispatcherServletxác định chế độ xem sẽ hiển thị kết quả, nó sẽ được hiển thị dưới dạng phản hồi.

Cuối cùng, DispatcherServlettrả về Responseđối tượng cho khách hàng.


47

DispatcherServletlà triển khai mô hình bộ điều khiển phía trước của Spring MVC .

Xem mô tả trong các tài liệu mùa xuân ở đây .

Về cơ bản, đó là một servlet nhận yêu cầu đến và ủy thác xử lý yêu cầu đó cho một trong số các trình xử lý, ánh xạ của nó là cụ thể trong DispatcherServletcấu hình.


Có phải nó giống như các sự kiện trong Flex, nơi tôi nhận các sự kiện từ một MXML này đến một máy chủ khác hoặc đến máy chủ. Tôi có thể có nhiều hơn một DispatcherServlet trong ứng dụng của mình không. Do mỗi tệp lớp có một DispatcherServlet riêng.
Kevin

Thường chỉ có một bộ điều khiển phía trước. Điều này là bất kể mô hình và quan điểm bạn có. Nó chỉ mang lại các mô hình cụ thể và quan điểm với nhau.
BalusC

2
@theband: Bạn có thể có nhiều DispatcherServlets, nếu kiến ​​trúc của bạn có ý nghĩa hơn theo cách đó, nhưng thường thì không có lý do gì.
skaffman

47

Tôi biết câu hỏi này đã được đánh dấu là đã được giải quyết nhưng tôi muốn thêm một hình ảnh mới hơn để giải thích chi tiết về mẫu này (nguồn: spring in action 4):

nhập mô tả hình ảnh ở đây

Giải trình

Khi yêu cầu rời khỏi trình duyệt (1) , nó sẽ mang thông tin về những gì người dùng đang yêu cầu. Ít nhất, yêu cầu sẽ được mang theo URL được yêu cầu. Nhưng nó cũng có thể mang theo dữ liệu bổ sung, chẳng hạn như thông tin được gửi bởi người dùng.

Điểm dừng đầu tiên trong hành trình của yêu cầu là tại Spring's DispatcherServlet. Giống như hầu hết các khung web dựa trên Java, các kênh Spring MVC yêu cầu thông qua một bộ điều khiển phía trước. Bộ điều khiển phía trước là một mẫu ứng dụng web phổ biến trong đó một servlet ủy thác trách nhiệm cho một yêu cầu cho các thành phần khác của ứng dụng để xử lý thực tế. Trong trường hợp của Spring MVC, DispatcherServlet là bộ điều khiển phía trước. Công việc của DispatcherServlet là gửi yêu cầu tới bộ điều khiển Spring MVC. Bộ điều khiển là một thành phần Spring xử lý yêu cầu. Nhưng một ứng dụng thông thường có thể có một vài bộ điều khiển và DispatcherServlet cần một số trợ giúp để quyết định bộ điều khiển nào sẽ gửi yêu cầu đến. Vì vậy, DispatcherServlet tư vấn một hoặc nhiều ánh xạ xử lý (2)để tìm ra điểm dừng tiếp theo của yêu cầu sẽ ở đâu. Ánh xạ xử lý chú ý đặc biệt đến URL được thực hiện theo yêu cầu khi đưa ra quyết định. Khi đã chọn một bộ điều khiển thích hợp, DispatcherServlet sẽ gửi yêu cầu theo cách vui vẻ của nó tới bộ điều khiển được chọn (3). Tại bộ điều khiển, yêu cầu giảm tải trọng của nó (thông tin được gửi bởi người dùng) và kiên nhẫn chờ đợi trong khi bộ điều khiển xử lý thông tin đó. (Trên thực tế, bộ điều khiển được thiết kế tốt sẽ tự xử lý ít hoặc không xử lý và thay vào đó ủy thác trách nhiệm cho logic nghiệp vụ cho một hoặc nhiều đối tượng dịch vụ.) người dùng và hiển thị trong trình duyệt. Thông tin này được gọi là mô hình. Nhưng việc gửi thông tin thô trở lại cho người dùng không phải là thông thường, nó cần được định dạng theo định dạng thân thiện với người dùng, điển hình là HTML. Vì thế, thông tin cần phải được cung cấp cho một khung nhìn, điển hình là Trang máy chủ Java (JSP). Một trong những điều cuối cùng mà bộ điều khiển thực hiện là đóng gói dữ liệu mô hình và xác định tên của chế độ xem sẽ hiển thị đầu ra. Sau đó, nó sẽ gửi yêu cầu, cùng với mô hình và tên xem, trở lại với DispatcherServlet(4) . Để bộ điều khiển không được ghép nối với một khung nhìn cụ thể, tên khung nhìn được gửi lại cho DispatcherServlet không xác định trực tiếp một tệp JSP cụ thể. Nó thậm chí không nhất thiết phải đề xuất rằng khung nhìn là một tệp JSP. Thay vào đó, nó chỉ mang một tên logic sẽ được sử dụng để tra cứu chế độ xem thực tế sẽ tạo ra kết quả. DispatcherServlet giới thiệu một trình phân giải khung nhìn (5) để ánh xạ tên khung nhìn logic thành một triển khai khung nhìn cụ thể, có thể có hoặc không phải là một tệp JSP. Bây giờ, DispatcherServlet biết chế độ xem nào sẽ hiển thị kết quả, công việc của yêu cầu gần như đã kết thúc. Điểm dừng cuối cùng của nó là ở phần thực hiện view (6), điển hình là một tệp JSP, nơi nó cung cấp dữ liệu mô hình. Công việc của yêu cầu cuối cùng đã được thực hiện. Khung nhìn sẽ sử dụng dữ liệu mô hình để hiển thị đầu ra sẽ được đưa trở lại máy khách bởi đối tượng phản hồi (không quá chăm chỉ) (7) .


Tôi có một câu hỏi, làm thế nào nó chọn khung nhìn trong trường hợp trả về đối tượng JSON mà chúng ta thấy trong trình duyệt, nó có trở về cùng một URI không nếu không có khung nhìn logic nào được chọn?
Nesrin

1
@Nesrin đã lâu rồi kể từ khi bạn hỏi nhưng đây là câu trả lời: Bạn đặt một chú thích đặc biệt ngay phía trên @Controllerphương thức được gọi là @ResponseBodyphản hồi trả về phải được viết trực tiếp trên thân phản hồi HTTP, không được đặt trong Mô hình hoặc được giải quyết dưới dạng xem .
bảng điều khiển

6

Chúng ta có thể nói như DispatcherServletchăm sóc mọi thứ trong Spring MVC.

Tại web container khởi động:

  1. DispatcherServletsẽ được tải và khởi tạo bằng init()phương thức gọi
  2. init()của DispatcherServletsẽ cố gắng để xác định các tài liệu Cấu hình mùa xuân với quy ước đặt tên như "servlet_name-servlet.xml"sau đó tất cả đậu có thể được xác định.

Thí dụ:

public class DispatcherServlet extends HttpServlet {

    ApplicationContext ctx = null;

    public void init(ServletConfig cfg){
        // 1. try to get the spring configuration document with default naming conventions
        String xml = "servlet_name" + "-servlet.xml";

        //if it was found then creates the ApplicationContext object
        ctx = new XmlWebApplicationContext(xml);
    }
    ...
}

Vì vậy, nói chung, DispatcherServletbắt URI yêu cầu và bàn giao HandlerMapping. HandlerMappingtìm kiếm ánh xạ bean với phương thức của bộ điều khiển, trong đó bộ điều khiển trả về tên logic (view). Sau đó, tên logic này được gửi đến DispatcherServletbởi HandlerMapping. Sau đó DispatcherServletnói ViewResolvercho vị trí đầy đủ các quan điểm bằng cách thêm tiền tố và hậu tố, sau đó DispatcherServletcung cấp cho xem cho khách hàng.


Đây là một lời giải thích tốt đẹp. Điểm số 2 của bạn nói rằng DispatcherServlet sẽ cố gắng xác định Tài liệu cấu hình mùa xuân bằng các quy ước đặt tên như "servlet_name-servlet.xml". Tuy nhiên, tôi đã thấy các dự án chỉ sử dụng tên như "người điều phối" và nó hoạt động tốt. Tôi cũng đã thử điều đó. Nhưng tôi không biết tại sao?
Subhasish Bhattacharjee

0

Bộ điều khiển bộ điều phối được hiển thị trong hình, tất cả các yêu cầu đến được chặn bởi bộ điều phối bộ điều phối hoạt động như bộ điều khiển phía trước. Bộ điều phối công cụ nhận được một mục để ánh xạ xử lý từ tệp XML và gửi yêu cầu tới Bộ điều khiển.


-1
<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
    <context:component-scan base-package="com.demo" />
    <context:annotation-config />

    <mvc:annotation-driven />


    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp" />

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="datasource" />
    </bean> 

          <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
        <property name="url" value="jdbc:mysql://localhost:3306/employee" />
        <property name="username" value="username" />
        <property name="password" value="password" />
    </bean> 

</beans>
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.