Co to jest Servlet Dispatchera na wiosnę?


195

Na tym obrazku (który dostałem stąd ) żądanie HTTP wysyła coś do serwletu Dispatchera.

wprowadź opis zdjęcia tutaj

Moje pytanie brzmi: co robi serwlet Dispatcher ?

Czy to coś w rodzaju pobrania informacji ze strony internetowej i przekazania ich kontrolerowi?

Odpowiedzi:


202

Zadaniem DispatcherServlet jest pobranie przychodzącego identyfikatora URI i znalezienie odpowiedniej kombinacji procedur obsługi (ogólnie metod klas Controller ) i widoków (ogólnie stron JSP), które łączą się, tworząc stronę lub zasób, który powinien zostać znaleziony w tym miejscu.

mogę mieć

  • plik /WEB-INF/jsp/pages/Home.jsp
  • i metoda na klasie

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

Dyspozytor aplet jest bit, który „wie”, aby wywołać tę metodę, gdy przeglądarka żąda strony, i połączyć swoje wyniki z pliku JSP pasującego do dokumentu HTML.

Jak to osiągnąć, różni się znacznie w zależności od konfiguracji i wersji Spring.

Nie ma również powodu, aby końcowym rezultatem były strony internetowe. Może zrobić to samo, aby zlokalizować punkty końcowe RMI , obsłużyć żądania SOAP , wszystko, co może wejść do serwletu.


4
Świetne riposte, teraz pytanie, w jaki sposób DispatcherServlet identyfikuje także nazwę klasy i nazwę metody. Czy możesz mi pokazać przykład konfiguracji, w której mam dwie klasy i dwie nazwy metod oraz sposób, w jaki DispatcherServlet łapie właściwe żądanie.
Kevin

10
Właściwie skanuje ścieżkę klasy podczas uruchamiania w poszukiwaniu tej adnotacji i dokonuje mapowania „/pages/Home.html” na metodę Class +. Jeśli masz dwie metody, w których obie mają „/pages/Home.html” bez żadnych innych ograniczeń w ich adnotacjach, byłby to błąd i spowoduje odrzucenie wyjątków. Możesz również połączyć to z XML, jeśli jesteś oldschool.
Affe

2
Czy potrzebujemy Dispatcher Servletpliku xml, gdy korzystamy z Adnotacji @RestController?
viper

1
@viper w pliku web.xml zawsze musimy konfigurować serwlet programu rozsyłającego, nawet jeśli korzystasz z adnotacji lub konfiguracji xml
Mahender Reddy Yasa

Czy jest jakiś inny rodzaj serwletu?
Minh Nghĩa

72

W Spring MVC wszystkie przychodzące żądania przechodzą przez jeden serwlet. Ten serwlet - DispatcherServlet- jest kontrolerem przednim. Kontroler frontowy to typowy wzorzec projektowy podczas tworzenia aplikacji internetowych. W takim przypadku pojedynczy serwlet odbiera wszystkie żądania i przenosi je do wszystkich innych komponentów aplikacji.

Zadaniem tego DispatcherServletjest wysłanie żądania do określonego kontrolera Spring MVC.

Zwykle mamy wiele kontrolerów i DispatcherServletodwołuje się do jednego z następujących maperów w celu ustalenia kontrolera docelowego:

Jeśli nie zostanie wykonana żadna konfiguracja, DispatcherServletzastosuje BeanNameUrlHandlerMappingi DefaultAnnotationHandlerMappingdomyślnie.

Po zidentyfikowaniu kontrolera docelowego DispatcherServletwysyła do niego żądanie. Kontroler wykonuje pewne prace zgodnie z żądaniem (lub deleguje je do innych obiektów) i wraca z powrotem do DispatcherServletmodelu i nazwy widoku.

Nazwa Widoku jest tylko logiczną nazwą. Ta logiczna nazwa jest następnie używana do wyszukiwania rzeczywistego Widoku (aby uniknąć sprzężenia ze sterownikiem i konkretnego Widoku). Następnie DispatcherServletodnosi się do ViewResolveri odwzorowuje logiczną nazwę Widoku na konkretną implementację Widoku.

Niektóre możliwe wdrożenia ViewResolverto:

Kiedy DispatcherServletokreśla widok, w którym zostaną wyświetlone wyniki, zostanie wyświetlony jako odpowiedź.

Na koniec DispatcherServletzwraca Responseobiekt z powrotem do klienta.


47

DispatcherServletjest implementacją wzorca kontrolera przedniego Spring MVC .

Zobacz opis w dokumentach wiosennych tutaj .

Zasadniczo jest to serwlet, który przyjmuje przychodzące żądanie i przekazuje przetwarzanie tego żądania jednemu z wielu programów obsługi, których mapowanie jest specyficzne w DispatcherServletkonfiguracji.


Czy to coś takiego jak wydarzenia w Flex, gdzie dostaję zdarzenia wysyłania z jednego MXML na inny lub na serwer. Czy mogę mieć więcej niż jedną usługę DispatcherServlet w mojej aplikacji? Czy pliki każdej klasy mają osobne DispatcherServlet.
Kevin

Zwykle jest tylko jeden kontroler z przodu. Jest to niezależne od posiadanych modeli i widoków. Po prostu łączy określone modele i widoki.
BalusC

2
@theband: Użytkownik może mieć wiele DispatcherServlets, jeśli architektura większy sens w ten sposób, ale zazwyczaj nie ma powodu do.
skaffman

47

Wiem, że to pytanie jest już oznaczone jako rozwiązane, ale chcę dodać nowszy obraz szczegółowo wyjaśniający ten wzór (źródło: wiosna w akcji 4):

wprowadź opis zdjęcia tutaj

Wyjaśnienie

Gdy żądanie opuszcza przeglądarkę (1) , przenosi informacje o tym, o co prosi użytkownik. Żądanie będzie zawierać przynajmniej żądany adres URL. Może jednak również zawierać dodatkowe dane, takie jak informacje przesłane w formularzu przez użytkownika.

Pierwszym przystankiem w podróży żądania jest Spring DispatcherServlet. Podobnie jak większość frameworków internetowych opartych na Javie, Spring MVC kieruje żądania przez jeden serwlet kontrolera z przodu. Kontroler frontowy to wspólny wzorzec aplikacji WWW, w którym pojedynczy serwlet przekazuje odpowiedzialność za żądanie innym komponentom aplikacji w celu wykonania rzeczywistego przetwarzania. W przypadku Spring MVC DispatcherServlet jest kontrolerem przednim. Zadaniem DispatcherServlet jest wysłanie żądania do kontrolera Spring MVC. Kontroler to komponent Spring, który przetwarza żądanie. Ale typowa aplikacja może mieć kilka kontrolerów, a DispatcherServlet potrzebuje pomocy przy podejmowaniu decyzji, do którego kontrolera wysłać zapytanie. Zatem DispatcherServlet sprawdza jedno lub więcej mapowań modułu obsługi (2)dowiedzieć się, gdzie będzie następny przystanek żądania. Podczas mapowania program obsługi zwraca szczególną uwagę na adres URL przenoszony przez żądanie. Po wybraniu odpowiedniego kontrolera DispatcherServlet wysyła żądanie w wesołej drodze do wybranego kontrolera (3). W kontrolerze żądanie opuszcza swój ładunek (informacje przesłane przez użytkownika) i cierpliwie czeka, aż kontroler przetwarza te informacje. (Właściwie dobrze zaprojektowany kontroler sam wykonuje niewiele przetwarzania lub wcale go nie przekazuje i zamiast tego przekazuje odpowiedzialność za logikę biznesową jednemu lub większej liczbie obiektów usług.) Logika wykonywana przez kontroler często skutkuje pewnymi informacjami, które należy przenieść z powrotem do użytkownika i wyświetlane w przeglądarce. Informacje te są nazywane modelem. Ale wysyłanie surowych informacji do użytkownika nie jest wystarczające - musi być sformatowane w formacie przyjaznym dla użytkownika, zwykle HTML. W tym celu należy podać informacje do widoku, zazwyczaj strony JavaServer (JSP). Jedną z ostatnich rzeczy, które robi kontroler, jest spakowanie danych modelu i zidentyfikowanie nazwy widoku, który powinien renderować dane wyjściowe. Następnie wysyła żądanie wraz z modelem i nazwą widoku z powrotem do DispatcherServlet(4) . Aby kontroler nie został połączony z konkretnym widokiem, nazwa widoku przekazana do DispatcherServlet nie identyfikuje bezpośrednio konkretnego JSP. To niekoniecznie sugeruje, że widok jest JSP. Zamiast tego nosi tylko logiczną nazwę, która będzie używana do wyszukiwania rzeczywistego widoku, który da wynik. DispatcherServlet konsultuje się z resolverem widoku (5) w celu odwzorowania logicznej nazwy widoku na konkretną implementację widoku, która może, ale nie musi być JSP. Teraz, gdy DispatcherServlet wie, który widok wyświetli wynik, zadanie żądania dobiega końca. Ostatnim przystankiem jest wdrożenie widoku (6), zwykle plik JSP, w którym dostarcza dane modelu. Zadanie żądania zostało w końcu wykonane. Widok użyje danych modelu do renderowania danych wyjściowych, które zostaną przeniesione z powrotem do klienta przez (nie tak pracowity) obiekt odpowiedzi (7) .


Mam pytanie, w jaki sposób wybiera widok w przypadku zwrotu obiektu JSON, który widzimy w przeglądarce, czy powraca do tego samego identyfikatora URI, jeśli nie wybrano widoku logicznego?
Nesrin

1
@Nesrin minęło wiele lat, odkąd zapytałeś, ale oto odpowiedź: umieściłeś specjalną adnotację tuż nad @Controllerwywoływaną metodą, @ResponseBodywskazującą, że zwrócona odpowiedź powinna być zapisana bezpośrednio w treści odpowiedzi HTTP, nie należy jej umieszczać w Modelu ani być rozpatrywana jako widok w ogóle .
deska rozdzielcza

6

Możemy powiedzieć, jak DispatcherServletdbanie o wszystko w Spring MVC.

Przy uruchomieniu kontenera internetowego:

  1. DispatcherServletzostanie załadowany i zainicjowany przez wywołanie init()metody
  2. init()z DispatcherServletspróbuje zidentyfikować dokumencie konfiguracji wiosnę z konwencji nazewnictwa jak "servlet_name-servlet.xml"to wszystkie ziarna mogą być identyfikowane.

Przykład:

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);
    }
    ...
}

Ogólnie rzecz biorąc, DispatcherServletprzechwytywanie URI żądania i przekazanie do HandlerMapping. HandlerMappingwyszukiwanie fasoli odwzorowującej za pomocą metody kontrolera, w której kontroler zwraca nazwę logiczną (widok). Następnie ta logiczna nazwa jest wysyłana DispatcherServletprzez HandlerMapping. Następnie DispatcherServletpowiedz, ViewResolveraby podać pełną lokalizację widoku, dodając prefiks i sufiks, a następnie DispatcherServletpodaj widok klientowi.


To miłe wytłumaczenie. Twój punkt 2 mówi, że DispatcherServlet spróbuje zidentyfikować dokument konfiguracji wiosny z konwencjami nazewnictwa, takimi jak „nazwa_serwera-serwlet.xml”. Widziałem jednak projekty, które używały tylko nazwy „dyspozytor” i działa dobrze. Ja też tego spróbowałem. Ale nie wiem dlaczego?
Subhasish Bhattacharjee

0

Kontroler dyspozytora jest pokazany na rysunku, wszystkie przychodzące żądania są przechwytywane przez serwlet dyspozytora, który działa jako kontroler frontowy. Serwlet dyspozytora otrzymuje wpis do mapowania modułu obsługi z pliku XML i przekazuje zapytanie do kontrolera.


-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>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.