Передний контроллер является наиболее основной частью всей структуры MVC. В основном он используется для перехвата внешних запросов, которые соответствуют требованиям и распределяют запросы различным контроллерам для обработки. Согласно результатам обработки контроллера, он генерирует соответствующие ответы и отправляет их клиенту. Фронт-контроллер может быть реализован с использованием фильтра (Struts2 использует этот метод) или сервлета (Spring MVC Framework).
Как предварительный контроллер, DispatcherServlet является входом на веб-сервер и является наиболее важным классом Spring MVC. Благодаря своему жизненному циклу понимание веб -сервера может быть углублено.
Жизненный цикл сервлета
Во -первых, давайте вспомним жизненный цикл сервлета:
Жизненный цикл сервлета разделен на три этапа: [подробное объяснение жизненного цикла сервлета и принципа работы]
1. Метод init () называется init () на этапе инициализации. После того, как сервлет загружен, контейнер сервлета создает экземпляр сервлета и вызывает метод init () init () сервлета для инициализации. Метод init () называется только один раз в течение всей жизни сервлета.
2. Позвоните в метод Service () в ответ на этап запроса клиента
3. Call Discoust () Метод на стадии завершения
Фаза инициализации сервлета
В следующие моменты контейнер сервлета загружает сервлет:
1. Когда контейнер сервлета запускается, некоторые сервлеты загружаются автоматически. Чтобы реализовать его, вам нужно только добавить следующий код между <servlet> </servlet> в файле web.xml:
<loadon-startup> 1 </loadon-startup>
2. После запуска контейнера сервлета клиент впервые отправляет запрос в сервлет
3. После обновления файла класса Сервлета, перезагрузите сервлет
Структура диспетчера
После рассмотрения вышеупомянутых знаний, давайте посмотрим на структуру DispatcherServlet:
DispatcherServlet наследует от абстрактного класса: Frameworkservlet, косвенно наследует httpservlet (Frameworkservlet от наследства от httpservletbean и Httpservlecebean от Httpservlet)
Инициализация сервлета
Protected void initstrategies (контекст ApplicationContext) {initmultipartresolver (context); // Загрузка файла и parse. Если тип запроса является многоуточным, загрузить файл и проанализировать через Multiprestrolver; initlocaleresolver (контекст); // локализация диаграмма инициализации (контекст); // анализ темы inithandlermappings (контекст); // отображение запросов на процессор InithandlerAdapters (контекст); // Картирование нескольких типов процессоров InithandlerexceptionResolvers (контекст); // Поддерживать несколько типов процессоров через HandlerDapter; // Если исключение встречается во время выполнения, оно будет передано HandleRexceptionResolver, чтобы Parse initRequestToviewNAMETRANSLATATOR (контекст); // непосредственно анализировать запрос в имени представления initViewResolvers (контекст); // Установите имя логического представления в конкретное представление через ViewResolver, чтобы реализовать initflashmapmanager (context); // Флэш -менеджер карты}Как обрабатывать запросы:
Метод обслуживания сервлета обрабатывает HTTP -запросы.
Frameworkservlet.java определяет методы обслуживания и уничтожения сервлета, как показано ниже:
/** * Переопределить реализацию родительского класса, чтобы перехватить запросы Patch *. */ @Override Protected void Service (httpservlectrequest, httpservletresponse response) throws servletexception, ioexception {string method = request.getmethod (); if (method.equalsignorecase (requestmethod.patch.name ())) {processrequest (request, response); } else {super.service (запрос, ответ); }}Мы знаем, что существуют семь типов типов HTTP -запросов (плюс опция), которые определены следующим образом:
public enum requestmethod {get, Head, Post, Pult, Patch, Delete, Options, Trace} Service () Frameworkservlet обрабатывает различные запросы. Мы используем общие посты, чтобы проиллюстрировать:
/*** Обработайте этот запрос, публикует событие независимо от результата. * <p> Фактическая обработка событий выполняется методом шаблона Abstract * {@link #doservice}. *; Бросаемый failureCause = null; Localecontext premorlocalecontext = localecontextholder.getlocalecontext (); Localecontext localecontext = buildlocalecontext (запрос); RequestAttributes premorattributes = requestContextholder.getRequestattributes (); Servletrequestattributes requestattributes = buildRequestattributes (запрос, ответ, предыдущий аттрибут); Webasyncmanager asyncmanager = webasyncutils.getasyncmanager (запрос); Asyncmanager.registerCallableInterceptor (FrameworkServlet.class.getName (), новый запрос bindingInterceptor ()); initContexTholders (запрос, LocalEcontext, requestAttributes); try {doservice (запрос, ответ); } catch (ServletException ex) {failUrecause = ex; бросить бывш; } catch (ioException ex) {failUrecause = ex; бросить бывш; } catch (throwable ex) {failUrecause = ex; бросить новое вложенное заверкания, («Обработка запроса не удалась», Ex); } наконец {resetContexTholders (запрос, предыдущий токал. if (requestattributes! = null) {requestattributes.requestcompleted (); } if (logger.isdebugenabled ()) {if (failurecause! = null) {this.logger.debug ("не может заполнить запрос", failurecause); } else {if (asyncmanager.isconCurrentHandlingStarted ()) {logger.debug («Ответ открыт для одновременной обработки»); } else {this.logger.debug ("успешно заполнил запрос"); }}} publishRequestHandledEvent (запрос, startTime, failureCause); }} Frameworkservlet абстрактно определяет поток обработки и оставляет его подклассам для реализации метода и завершает конкретную обработку запросов.
/** * Подклассы должны реализовать этот метод для выполнения работы по обработке запросов, * получение централизованного обратного вызова для получения, публикации, поместите и удаления. * <p> Контракт по существу такой же, как и для обычно переопределенных * {@code Doget} или {@code dopost} httpservlet. * <p> Этот класс перехватывает звонки, чтобы обеспечить, чтобы обработка исключений и * публикация событий имела место. * @param запрос текущий http -запрос * @param ответ текущий http response * @throws исключение в случае какого -либо сбоя обработки * @see javax.servlet.http.httpservlet#doget * @see javax.servlet.http.httpservelt#dopost */ protected voidervice (htttpeser#doposts voidervice (htttp.httpservel Httpservletresponse response) бросает исключение;Конкретная реализация заключается в следующем:
/** * Раскрывает специфичные для диспетчеры атрибуты запроса и делегаты в {@link #dodispatch} * для фактического отправки. */ @Override Protected void DoService (httpservletrequest, httpservletresponse response) throws exection {if (logger.isdebugenabled ()) {string resumed = webasyncutils.getAsyncmanager (request) .hasconCurrentResult ()? "Возобновил": ""; logger.debug ("DispatcherServlet с именем" + getServletName () + "'" + возобновление + "обработка" + request.getMethod () + "запрос [" + getRequesturi (запрос) + "]"); } // Сделайте снимок атрибутов запроса в случае включения, //, чтобы иметь возможность восстановить исходные атрибуты после включения. Map <string, object> attributessnapshot = null; if (webutils.isincludeRequest (request)) {attributessnapshot = new hashmap <string, object> (); Enumeration <?> Attrnames = request.getattributeNames (); while (attrnames.hasmoreElements ()) {string attrname = (string) attrnames.nextelement (); if (this.cleanupaterinclude || attrname.startswith ("org.springframework.web.servlet")) {attributessnapshot.put (attrname, request.getattribute (attrname)); }}}} // Сделайте фреймворные объекты, доступные для обработчиков и представления объектов. request.setattribute (web_application_context_attribute, getWebApplicationContext ()); request.setattribute (locale_resolver_attribute, this.localeresolver); request.setattribute (theme_resolver_attribute, this.themeresolver); request.setattribute (theme_source_attribute, getTheMesource ()); Flashmap Inputflashmap = this.flashmapmanager.retrieveandupdate (запрос, ответ); if (inputflashmap! = null) {request.setattribute (input_flash_map_attribute, collections.unmodifiablemap (inputflashmap)); } request.setattribute (output_flash_map_attribute, new Flashmap ()); request.setattribute (flash_map_manager_attribute, this.flashmapmanager); try {dodispatch (запрос, ответ); } наконец {if (webasyncutils.getasyncmanager (request) .isconcorrenthandlingstarted ()) {return; } // Восстановите исходный снимок атрибута, в случае включения. if (attributessnapshot! = null) {RestoreAttributesafterinclude (запрос, attributessnapshot); }}}Основной момент, как реализация дистрибьютора запросов:
Функции: 1. Распределить запрос на обработчик (получите отношение отображения сервлета в порядке конфигурации); 2. Запрос первого обработчика, который может быть обработан на основе обработчиков, установленных сервлетом; 3. Обработчик запускает обработку запроса
/*** Обработайте фактическую отправку в обработчик. * <p> Обработчик будет получен путем применения ручных работ сервлета по порядку. * HandlerAdapter будет получен путем запроса установленных портлеров Сервлета *, чтобы найти первый, который поддерживает класс обработчика. * <p> Все методы HTTP обрабатываются этим методом. Сами сами должны решить, какие методы приемлемы. * @param Запрос Текущий http -запрос * @param Ответ Текущий Ответ http * @throws Exception В случае какого -либо сбоя обработки */ Защищенный void Dodispatch (httpservlectrequest, httpservletresponse response). Ответ исключает {httpservlectrequest reception = recept; HandleRexeCutionChain MapedHandler = null; Boolean MultipartrequestParsed = false; Webasyncmanager asyncmanager = webasyncutils.getasyncmanager (запрос); try {modelandview mv = null; Исключение DispatchException = null; try {processedRequest = checkmultipart (request); MultipartRequestParsed = (ProcessEdRequest! = запрос); // Определите обработчик для текущего запроса. mapedHandler = gethandler (ProcessEdRequest); if (mapedHandler == null || mapedHandler.gethandler () == null) {noohhandlerfound (processedRequest, response); возвращаться; } // Определите адаптер обработчика для текущего запроса. HandlerAdapter ha = gethandlerAdapter (mappenhandler.gethandler ()); // Процесс последнего модифицированного заголовка, если он поддерживается обработчиком. String method = request.getmethod (); Boolean ISGet = "GET". EQUALS (MEDEA); if (isget || "head" .equals (method)) {long lastmodified = ha.getlastmodified (request, mappenhandler.gethandler ()); if (logger.isdebugenabled ()) {logger.debug («Последнее модифицированное значение для [" + getRequesturi (запрос) + "] IS:" + LastModified); } if (new ServletWebRequest (запрос, ответ) .CHECKNOTMODIFIFIT (LASTMODIFIT) && isget) {return; }} if (new servletwebrequest (request, response) .checknotmodified (lastmodified) && isget) {return; }} if (! mapedHandler.applyprehandle (processedRequest, response)) {return; } попробуйте {// фактически вызвать обработчик. mv = ha.h.handle (processedRequest, response, mappenhandler.gethandler ()); } наконец {if (asyncmanager.isconcorrenthandlingStarted ()) {return; }} ApplyDefaultViewName (запрос, MV); mappenhandler.applyposthandle (ProcessedRequest, ответ, MV); } catch (Exception ex) {dispatchException = ex; } processDispatchResult (ProcessEdRequest, ответ, MapedHandler, MV, DispatchException); } catch (Exception ex) {triggerAfterCompletion (ProcessEdRequest, ответ, MapedHandler, Ex); } catch (erry err) {triggerafterCompletionWitherRor (ProcessEdRequest, ответ, MapedHandler, ERR); } наконец {if (asyncmanager.isconcurrenthandlingStarted ()) {// вместо PosThandle и Aftercompletion mappenHandler.applyafterCorrentHandlingStarted (ProcessEdRequest, ответ); возвращаться; } // Очистите любые ресурсы, используемые Multipart Request. if (multipartrequestparsed) {lecleupmultipart (processedRequest); }}}Уничтожение сервлета
/*** Закройте WebApplicationContext этого сервлета. * @see org.springframework.context.configurableapplicationContext#close () */ @Override public void destress () {getServletContext (). ("Уничтожение Spring Framewrkservlet '" + getServletName () + "' '); // только вызов close () на WebApplicationContext, если локально управляется ... if (this.WebApplicationContext EncementOf configurableAppliclicationContext &&! This.WebApplicationContextIntected) {((configurableApplicalationContext) this.WebApplicationContext) .close (); }}краткое содержание:
Из-за ограничений главы в этой статье только вводит процесс обработки запросов и не проводит углубленный анализ кода. Следующая статья начнется с деталей и проанализирует красоту весеннего кода.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.