Что такое диспетчерский сервлет весной?


195

В этом образе (который я получил отсюда ) HTTP- запрос отправляет что-то сервлету Dispatcher.

введите описание изображения здесь

Мой вопрос: что делает Dispatcher Servlet ?

Это что-то вроде извлечения информации с веб-страницы и передачи ее в контроллер?

Ответы:


202

Задача DispatcherServlet состоит в том, чтобы взять входящий URI и найти правильную комбинацию обработчиков (обычно это методы для классов Controller ) и представлений (обычно это JSP), которые объединяются, чтобы сформировать страницу или ресурс, который должен быть найден в этом месте.

Я мог бы иметь

  • файл /WEB-INF/jsp/pages/Home.jsp
  • и метод по классу

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

Грузоотправитель сервлет является бит , который «знает» , чтобы вызвать этот метод , когда браузер запрашивает страницу, и объединить свои результаты с согласующей JSP файл , чтобы сделать HTML документ.

Как это достигается, сильно зависит от конфигурации и версии Spring.

Также нет причины, по которой конечным результатом должны быть веб-страницы. Он может сделать то же самое, чтобы найти конечные точки RMI , обработать запросы SOAP , все, что может попасть в сервлет.


4
Отличный ответ, теперь вопрос, почему DispatcherServlet идентифицирует имя класса и имя метода тоже. Можете ли вы показать мне пример конфигурации, где у меня есть два класса и два имени метода и как DispatcherServlet ловит правильный запрос.
Кевин

10
Он на самом деле сканирует путь к классу при запуске для этой аннотации и создает отображение «/pages/Home.html» в метод Class +. Если у вас есть два метода, в обоих из которых есть «/pages/Home.html» без каких-либо других ограничений в их аннотациях, это будет ошибкой и вызовет исключения у вас. Вы также можете связать его вместе с XML, если вы старшеклассник.
Affe

2
Нужен ли нам Dispatcher ServletXML-файл при использовании Annotation Based @RestController?
гадюка

1
@viper в web.xml нам всегда нужно настраивать диспетчерский сервлет, даже если вы используете аннотации или конфигурации xml
Mahender Reddy Yasa

Есть ли другой тип сервлета?
Minh Ngh 1a

72

В Spring MVC все входящие запросы проходят через один сервлет. Этот сервлет - DispatcherServlet- это фронт-контроллер. Фронт-контроллер является типичным шаблоном проектирования при разработке веб-приложений. В этом случае один сервлет получает все запросы и передает их всем другим компонентам приложения.

Задача DispatcherServletсостоит в том, чтобы отправить запрос конкретному контроллеру Spring MVC.

Обычно у нас много контроллеров, и DispatcherServletдля определения целевого контроллера используется один из следующих картографов:

Если конфигурация не выполняется, DispatcherServletиспользуется BeanNameUrlHandlerMappingи DefaultAnnotationHandlerMappingпо умолчанию.

Когда целевой контроллер идентифицирован, DispatcherServletотправляет запрос к нему. Контроллер выполняет некоторую работу в соответствии с запросом (или делегирует его другим объектам) и возвращает обратно DispatcherServletс моделью и именем представления.

Имя представления является только логическим именем. Это логическое имя затем используется для поиска фактического вида (чтобы избежать связи с контроллером и конкретным видом). затемDispatcherServlet обращается к ViewResolverи сопоставляет логическое имя представления с конкретной реализацией представления.

Некоторые возможные реализации ViewResolver :

Когда DispatcherServlet определяется представление, которое будет отображать результаты, оно будет отображено как ответ.

Наконец, DispatcherServletвозвращает Responseобъект обратно клиенту.


47

DispatcherServletэто реализация Spring MVC шаблона фронт-контроллера .

Смотрите описание в документации Spring здесь .

По сути, это сервлет, который принимает входящий запрос и делегирует обработку этого запроса одному из нескольких обработчиков, отображение которых зависит от DispatcherServletконфигурации.


Это что-то вроде событий во Flex, где я получаю события отправки из одного MXML в другой или на сервер. Могу ли я иметь более одного DispatcherServlet в моем приложении. У каждого файла классов есть отдельный DispatcherServlet.
Кевин

Там обычно только один фронт-контроллер. Это независимо от моделей и представлений, которые у вас есть. Он просто объединяет конкретные модели и взгляды.
BalusC

2
@theband: у вас может быть несколько DispatcherServlets, если ваша архитектура имеет больше смысла, но обычно нет причин для этого.
Скаффман

47

Я знаю, что этот вопрос помечен как уже решенный, но я хочу добавить более новое изображение, подробно объясняющее этот шаблон (источник: весна в действии 4):

введите описание изображения здесь

объяснение

Когда запрос покидает браузер (1) , он несет информацию о том, что запрашивает пользователь. По крайней мере, запрос будет содержать запрошенный URL. Но он также может содержать дополнительные данные, такие как информация, представленная пользователем в форме.

Первая остановка в путешествиях запроса - в DispatcherServlet Spring. Как и большинство веб-платформ на основе Java, Spring MVC направляет запросы через один сервлет фронт-контроллера. Фронт-контроллер - это общий шаблон веб-приложения, в котором один сервлет делегирует ответственность за запрос другим компонентам приложения для выполнения фактической обработки. В случае Spring MVC, DispatcherServlet является фронт-контроллером. Задача DispatcherServlet - отправить запрос на контроллер Spring MVC. Контроллер - это компонент Spring, который обрабатывает запрос. Но типичное приложение может иметь несколько контроллеров, и DispatcherServlet нужна некоторая помощь для определения, на какой контроллер отправлять запрос. Таким образом, DispatcherServlet обращается к одному или нескольким сопоставлениям обработчиков. (2)выяснить, где будет следующая остановка запроса. При сопоставлении обработчик обращает особое внимание на URL-адрес, передаваемый запросом. После того, как соответствующий контроллер был выбран, DispatcherServlet отправляет запрос на свой веселый путь выбранному контроллеру. (3), В контроллере запрос сбрасывает свою полезную нагрузку (информацию, представленную пользователем) и терпеливо ждет, пока контроллер обработает эту информацию. (На самом деле, хорошо спроектированный контроллер сам выполняет небольшую обработку или не выполняет ее и вместо этого передает ответственность за бизнес-логику одному или нескольким сервисным объектам.) Логика, выполняемая контроллером, часто приводит к некоторой информации, которую необходимо перенести обратно. пользователь и отображается в браузере. Эта информация называется моделью. Но отсылать необработанную информацию обратно пользователю недостаточно - ее необходимо отформатировать в удобном для пользователя формате, обычно в HTML. Для этого информация должна быть передана в представление, обычно на страницу JavaServer (JSP). Одна из последних вещей, которые выполняет контроллер, - упаковывает данные модели и идентифицирует имя представления, которое должно отображать выходные данные. Затем он отправляет запрос вместе с моделью и именем представления обратно в DispatcherServlet(4) . Чтобы контроллер не был связан с конкретным представлением, имя представления, переданное обратно в DispatcherServlet, напрямую не идентифицирует конкретный JSP. Это даже не означает, что представление является JSP. Вместо этого он несет только логическое имя, которое будет использоваться для поиска фактического представления, которое будет давать результат. DispatcherServlet консультируется с решателем представления (5) для сопоставления имени логического представления с конкретной реализацией представления, которая может быть или не быть JSP. Теперь, когда DispatcherServlet знает, какое представление будет отображать результат, работа запроса почти завершена. Его окончательная остановка - при реализации представления (6)обычно это JSP, куда он доставляет данные модели. Работа с запросом окончательно выполнена. Представление будет использовать данные модели для визуализации вывода, который будет возвращен клиенту (не очень трудоемким) объектом ответа (7) .


У меня есть вопрос, пожалуйста, как он выбирает представление в случае возврата объекта JSON, который мы видим в браузере, возвращает ли он тот же URI, если не выбрано логическое представление?
Несрин

1
@ Несрин, прошло уже много лет с тех пор, как вы спросили, но вот ответ: вы помещаете специальную аннотацию чуть выше @Controllerметода, который @ResponseBodyуказывает, что возвращаемый ответ должен быть непосредственно записан в теле ответа HTTP, а не помещен в модель или разрешен как представление вообще ,
панель приборов

6

Мы можем сказать, как DispatcherServletзаботиться обо всем в Spring MVC.

При запуске веб-контейнера:

  1. DispatcherServletбудет загружен и инициализирован вызовом init()метода
  2. init()of DispatcherServletбудет пытаться идентифицировать Spring Configuration Document с соглашениями по именованию, как "servlet_name-servlet.xml"тогда могут быть идентифицированы все bean-компоненты.

Пример:

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

Итак, в общем случае DispatcherServletзахватите URI запроса и передайте HandlerMapping. HandlerMappingbean-объект поиска с методом контроллера, где контроллер возвращает логическое имя (представление). Тогда это логическое имя отправить DispatcherServletпо HandlerMapping. Затем DispatcherServletпопросите указать ViewResolverполное местоположение просмотра, добавив префикс и суффикс, а затем DispatcherServletпредоставьте представление клиенту.


Это хорошее объяснение. Ваша точка номер 2 говорит, что DispatcherServlet попытается идентифицировать конфигурационный документ Spring с помощью соглашений об именах, таких как "servlet_name-servlet.xml". Тем не менее, я видел проекты, которые использовали имя как «диспетчер» только, и он работает нормально. Я тоже это попробовал. Но я не знаю, почему?
Subhasish Бхаттачарджи

0

Диспетчер диспетчера показан на рисунке, все входящие запросы перехвачены сервлетом диспетчера, который работает в качестве фронт-контроллера. Сервлет диспетчера получает запись для сопоставления обработчика из XML-файла и передает запрос контроллеру.


-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>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.