IOC Spring был проанализирован ранее («На основе нуля покажите исходный код Spring — инверсия управления IOC») и АОП(«Начиная с исходного кода, эта статья приведет вас к тому, чтобы понять Spring AOP-ориентированное программирование») исходный код, на этот раз для анализа SpringMVC. В этой статье сначала кратко описывается текущее использование SpringMVC, а затем благодаря простоте демонстрации у каждого есть предварительное впечатление об использовании, а затем складывается впечатление, чтобы увидеть исполняемый в нем распределенный исходный код.
Что такое Spring MVC и используем ли мы его до сих пор?
Spring MVC, официальное название на самом делеSpring Web MVC, имя пакета в Maven также будет spring-webmvc. С момента рождения Spring это была веб-архитектура, основанная на Servlet Api. Стоит отметить, что в Spring 5 была разработана новая веб-архитектура Flux, основанная на модели, управляемой событиями (похожей на nodejs). Я напишу статью, чтобы представить Flux в будущем, так что следите за обновлениями.
MVC, возможно, самая популярная модель взаимодействия с интерфейсом и сервером в «прошлом веке». Он включает модель (бизнес-модель), представление (пользовательское представление) и контроллер (контроллер), который организует каждую часть отдельно.Обработка абстракции и изоляции кода может быть описана как модель проектирования кода.
Однако с 2015 года, с появлением различных интерфейсных сред, отношения между интерфейсом и сервером получили дальнейшее развитие: от архитектуры MVC к архитектуре REST, которая разделяет интерфейс и серверную часть. В прошлом каждый запрос архитектуры MVC должен был проходить через процесс контроллер->модель->представление, который превратился в архитектуру REST, в которой внешний интерфейс запрашивает внутренний интерфейс и возвращает JSON.
Вопрос в том, используем ли мы SpringMVC? Ответ: не все. Front-end и back-end отделены от кода и деплоя, то есть back-end не воспринимает существование front-end, поэтому для back-end View (пользовательский вид) невозможно говорить о. Модель (бизнес-модель) отправляет изменение характера.Раньше это была Модель, необходимая фронтенду для чтения страницей, а теперь она отправляется на фронтенд в формате JSON, который свободно обрабатывается передняя часть.
В качестве ядра веб-фреймворка по-прежнему сохраняется Controller (контроллер). Итак, теперь все используют SpringMVC, чтобы больше использовать уровень контроллера. Конечно, в SpringMVC есть и другие компоненты, в том числе фильтр, Http-кэширование, веб-безопасность и другие. В этой статье рассматриваются только функции контроллера в архитектуре MVC, а основным компонентом контроллера является DispatcherServlet. Поэтому позже мы будем использовать Demo, чтобы постепенно понять, как DispatcherSevlet управляет распределением запросов.
Краткое введение в традиционный стартап SpringMVC
В традиционном SpringMVC необходимо настроить файлы web.xml и applicationContext.xml. Первая — это конфигурация, отвечающая за настройку инициализации проекта, например, сервлета, страницы приветствия и т. д., что является спецификацией JavaEE. Последняя — это конфигурация для инициализации Spring Context, в основном конфигурация Bean.
Как упоминалось ранее, SpringMVC — это архитектура, основанная на сервлетах, а DispatcherServlet — это сервлет, который SpringMVC перехватывает и обрабатывает все запросы, поэтому файлу web.xml необходимо настроить DispatcherServlet. Другими являются contextLoaderListener, который отвечает за загрузку всего содержимого контекста, кроме DispatcherServlet, и также должен указать файл конфигурации Spring (например, applicationContext.xml) через contextConfigLoader.
Затем, когда проект запустится, загрузка web.xml сначала выполнит contextLoaderListener для инициализации контекста приложения Spring. Когда приходит HTTP-запрос, он попадает на DispatcherServlet и позволяет ему выполнять обработку и распространение.
Веб-демонстрационная сборка SpringBoot
С момента появления аннотаций конфигурации Spring и SpringBoot все меньше и меньше людей пишут файлы конфигурации web.xml и applicationContext.xml. Но для того, чтобы непосредственно понять принцип работы Dispatcher, демонстрационная версия построена непосредственно с помощью запуска SpringBoot одним щелчком мыши.
Добавить зависимости веб-стартера напрямую
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
Посмотрите, что содержит этот стартер
Зеленое поле — это зависимость SpringMVC, красное поле — зависимость автоматической настройки Spring, а синее поле — зависимость встроенного кота. Версия Spring внутри — 5.0.8 RELEASE.Класс запуска SpringBoot
тестовый контроллер
После запуска программы введите в браузереhttp://localhost:8080/hello?name=Zack
.结果返回Hello Zack
.
Вышеизложенное является основным содержанием использования SpringMVC.Давайте посмотрим, как SpringMVC использует DispatcherServlet для перехвата и распространения.
Анализ исходного кода DispatcherServlet
Когда приходит запрос, сначала будут выполняться различные фильтры, чтобы отфильтровать окончательный требуемый запрос, а затем он упадет до **doService() в DispatcherServlet.метод. Этот метод заключается в предварительной установке некоторых специальных параметров запроса, а затемdoDispatch()** выполняет реальную обработку переадресации.
Посмотрите на комментарии ** Dodispatch () **
Функция этого метода заключается в выполнении обработчика, который фактически отправлен.- Handler получается по приоритету HandlerMapping. HandlerAdapter получается путем запроса HandlerAdapter, который DispatcherServlet загрузил и поддерживает обработчик.
- Все HTTP-запросы обрабатываются **doDispatch()**. В частности, какой метод обработки бизнес-логики зависит от HandlerAdapters или обработчиков.
Как видно из комментариев, ядро всей логики раздачи лежит в HandlerAdapter и Handler. Так что же это за две вещи?
Инструкция на официальном сайте
HandlerAdapter помогает DispatcherServlet вызывать соответствующий обработчик, игнорируя способ вызова конкретного обработчика. Например, при вызове контроллера в виде аннотации нужно обработать аннотацию, а в виде конфигурации xml нужно разобрать файл конфигурации. Этот адаптер должен помочь DispatcherServlet скрыть конкретные детали обработки.Что касается обработчика, то здесь нет четкого объяснения, но из исходного кода отладки мы можем обнаружить, что обработчик на самом деле является методом, который фактически выделен для конкретной потребности в обработке (сравните красный прямоугольник на рисунке ниже и контроллер демо выше).
назадdoDispatch()Исходный код этого метода см.getHandler(), **getHandlerAdapter()** — получить Handler и HandlerAdapter.
getHandler()
посмотриgetHandler()исходный код
Весь метод состоит всего из нескольких строк, но следует отметить два момента. Во-первых, метод возвращаетHandlerExecutionChainтип, а не обработчик. HandlerExecutionChainПо сути, это слой инкапсуляции Handler, а также он включает в себя перехватчик, соответствующий Handler, который используется для выполнения некоторых операций пре- и постобработки Handler.Еще один момент,HandlerExecutionChainпроходит по порядкуhandlerMappingsизъятые. ЭтоHandlerMappingЧто это такое?
Как видно из описания на официальном сайте, это запрос и обработчик (на самом делеHandlerExecutionChain), связанная карта, с точки зрения непрофессионала, представляет собой связь между логикой маршрутизации и обработки. В основном он имеет две реализации, одна из которыхRequestMappingHandlerMapping(методы аннотированной формы поддерживаются), другойSimpleUrlHandlerMapping(Поддерживает ресурсы URI, которые отображают регистрации).Можно предположить, что при запуске Spring будет сканировать аннотации и зарегистрированные статические ресурсы для инициализации этогоhandlerMappings. Конкретная логика таковаDispatcherServletсерединаinitHandlerMappingsвнутри метода.
В методе инициализации есть три основных шага:- Выньте Bean HandlerMapping из Spring ApplicationContext
- Затем расставьте приоритеты для bean-компонентов, взятых выше, в основном для сортировки аннотаций @Order.
- Если Бин не может быть извлечен выше, используется стратегия по умолчанию.
Для политики по умолчанию третьей точки можно найтиDispatcherServlet.propertiesЭтот файл настраивает некоторые классы HandlerMapping, HandlerAdapter и другие связанные классы по умолчанию.
в инициализацииhandlerMappingsПосле, если есть запрос, запрос возвращается к запросу маршрута, используяHandlerMappingсравните и наконец узнайтеHandler(HandlerExecutionChain).
getHandlerAdapter()
снятие фактической обработкиHandlerПосле этого нужно с его помощью узнать адаптер, который его поддерживает (HandlerAdapter). Лицом к лицу, как преждеHandlerAdapterОписание для демонстрации, поддержите этоHandlerдолжно бытьRequestMappingHandlerAdapter.
Эта логика также очень проста, она также проходит инициализированныйhandlerAdapters(Процесс инициализации аналогиченhandlerMappings), то для каждого конкретногоhandlerAdapter, вызовите его метод **support()**, чтобы узнать, поддерживается ли он.
Метод **supports()** также очень прост, просто используйте instanceof, чтобы определить, является ли обработчик классом, поддерживаемым самим адаптером.
HandlerAdapter.handle()
после полученияHandlerа такжеHandlerAdapterПосле этого можно выполнитьHandlerAdapterМетод handle в , который на самом деле является просто методом вызова Handler.
Давайте посмотрим на демонстрационный примерHttpRequestHandlerAdapterизhandle()реализация метода.
Этот метод заключается в использовании запроса и ответа HttpServlet для вызова метода в контроллере, написанном нами. Следует отметить, что этот метод возвращаетModelAndView, но мы больше не используем его на основе архитектуры Rest, поэтому метод возвращаетnullушел обратно.Пре- и постобработка обработчика
упомянутый ранееHandlerзаключен вHandlerExecutionChainВнутри он также содержит несколько пре- и пост-перехватчиков. Итак, выполнениеHandlerAdapter.handle()будет правильноHandlerExecutionChainпозвонить, выполнитьinterceptorМетоды предварительной и последующей обработки
Конкретная реализация заключается в выполненииinterceptor**предобработка()а такжеPostHandle () ** Способ.
Оглядываясь назад, что включает в себя пре- и постобработка? существуетHandlerInterceptorВ аннотации описаны три класса реализации, которыеUserRoleAuthorizationInterceptor(проверьте права пользователя),LocaleChangeInterceptor(изменить местное время),ThemeChangeInterceptor(изменить текущую тему). Как можно заметитьHandlerInterceptorЭто в основном некоторая предварительная обработка и инкапсуляция результата запроса.
Суммировать
Вышеупомянутое в SpringMVCDispatcherServletосновной процесс. Вот краткое изложение вышеизложенного:
- Эволюция интерфейсной и серверной архитектуры привела к изменениям в использовании SpringMVC с большим упором на «C».
- Ядром «С» являетсяDispatcherServletв методе **doDispatcher()**.
- Используя маршрут запроса, сравните с инициализированнымhandlerMappingsа такжеhandlerAdaptersполучено вhandlerа такжеhandlerAdapter.
- handlerупакован вHandlerExecutionChain, который также включаетhandlerпередние и задние интерцепторы.
- Наконец, используя режим адаптера, вызовитеHandlerAdapter.handle()метод выполненияhandlerСпецифическая бизнес-логика обработки.
- До и после выполнения определенной бизнес-логики инкапсуляция вHandlerExecutionChainПерехватчик внутри.
Для получения дополнительных технических статей и замечательных сухих товаров, пожалуйста, обратите внимание
Блог:zackku.com
Публичный аккаунт WeChat: Зак сказал код