Как фреймворки (например, Spring) настраивают контейнер сервлетов без web.xml? - PullRequest
0 голосов
/ 23 мая 2019

(Я уже знаю ответ, но, поскольку я часто переоцениваю ответ, поэтому я публикую его здесь в качестве документации для себя и других. Это рекомендуется в Stackoverflow. )

Фоновая заставка

Многие разработчики сервлетов прочитали книгу «Head First Serlet & JSP», чтобы сдать экзамен на сертифицированного разработчика веб-компонентов или просто изучить сервлеты. Но книга не обновлялась с 2009 года и охватывает только сервлет 2.4. С тех пор многое изменилось. Текущая последняя версия 4.0. Одна из вещей, которая изменилась, - это процесс загрузки веб-приложений сервлета, который может сделать неясным, что происходит во время запуска и как инициализируется веб-приложение.

Вопрос

В Servlet версии 2.4 и ниже, web.xml используется для полной настройки веб-приложений. Но более высокая версия, похоже, имеет другие способы настройки веб-приложений, не затрагивая web.xml и без аннотаций. Например, веб-фреймворки, представленные в виде файлов .jar, могут каким-то образом подключаться к контейнеру сервлета и добавлять сопоставления URL.

Как работает этот механизм?

1 Ответ

2 голосов
/ 23 мая 2019

Введение

В Servlet 2.4 (ноябрь 2003 г.) контейнер сервлета (например, Tomcat и Jetty) просто загрузил веб-приложение, выполнив поиск файла WEB-INF/web.xml (дескриптор развертывания ) , Файл web.xml содержит ссылки на сервлеты, фильтры и прослушиватели, а также связанные с ними шаблоны и параметры URL. С помощью web.xml контейнер сервлета точно знает, где найти все и как их настроить.

Поскольку Servlet 3.0 (декабрь 2009 г.), web.xml является необязательным, вместо него можно использовать аннотации или программную конфигурацию.

Аннотации простые, вы можете аннотировать сервлет, фильтр или прослушиватель с помощью @ javax.servlet.annotation. WebServlet , @ WebFilter и @ WebListener соответственно , который позволяет контейнеру сервлета находить и обнаруживать эти классы. Однако аннотации предоставляют меньше возможностей конфигурации, чем web.xml и программную конфигурацию.

Этот текст далее посвящен тому, как можно настроить программную конфигурацию и как она запускает Spring MVC. Это немного сложнее, чем аннотации, но дает вам и дизайнерам фреймворков больший контроль над процессом загрузки.

Если вы хотели использовать веб-фреймворк до Servlet 3.0, вам нужно было добавить сервлет или фильтр в ваш web.xml и настроить фреймворк оттуда. После этой инициализации вы можете начать писать классы (обычно не классы сервлетов), известные веб-инфраструктуре, для создания веб-приложения.

Начиная с Servlet 3.0, система является модульной. Это позволяет разработчикам каркаса и библиотеки инициализировать контейнер сервлета без необходимости конфигурирования каркаса через web.xml. Вы можете сразу же приступить к написанию определенных классов веб-фреймворка для создания веб-приложения, не касаясь классов сервлетов. (В Servlet 3.0 также возможно создать свой собственный web.xml и при этом позволить каркасу выполнять инициализацию каркаса, без определения в web.xml.)

Как фреймворк или библиотека могут автоматически подключаться к контейнеру Servlet?

При загрузке контейнер сервлетов сначала ищет дескриптор развертывания, расположенный в WEB-INF/web.xml. Если для этого файла для атрибута metadata-complete установлено значение false или он вообще не определен, контейнер также будет искать аннотированные классы, такие как @ WebServlet.

Помимо поиска web.xml и аннотированных классов, начиная с Servlet 3.0, контейнер также будет искать файлы META-INF/web-fragment.xml в файлах .jar, расположенных в каталоге WEB-INF/lib.

Файл web-фрагмент.xml представляет собой веб-фрагмент , который:

логическое разбиение веб-приложения таким образом, чтобы рамки, используемые в веб-приложении, могут определять все артефакты, не прося разработчиков редактировать или добавлять информацию в web.xml. Он может включать почти все те же элементы, что и web.xml. дескриптор использует. Однако элемент верхнего уровня для дескриптора ДОЛЖЕН быть веб-фрагментом, и соответствующий файл дескриптора ДОЛЖЕН быть вызван веб-fragment.xml. Элементы, относящиеся к упорядочению, также различаются между web-фрагмент.xml и web.xml

Содержимое файла web-фрагмент.xml похоже на файл web.xml, но с корневым элементом web-fragment вместо элемента web-app:

<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
              https://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
              version="3.0">
  <filter>
    <filter-name>FrameworkFilter</filter-name>
    <filter-class>framework.FrameworkFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>FrameworkFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-fragment>

Точный порядок загрузки одного файла web.xml и нескольких файлов web-фрагмента.xml можно настроить с помощью <absolute-ordering> и <ordering>.

Помимо веб-фрагментов, существует также программный метод разбиения веб-приложения: написание реализации интерфейса javax.servlet.ServletContainerInitializer. ServletContainerInitializer предоставляет доступ к ServletContext, который содержит методы для программного добавления сервлетов, фильтров и прослушивателей. Чтобы использовать ServletContainerInitializer, он должен быть указан в файле, расположенном в META-INF/services/javax.servlet.ServletContainerInitializer. Содержимое этого файла должно быть полным путем к классу реализации.

Как это работает для Spring MVC?

Хотя Spring MVC содержит web-fragment.xml, он не определяет никаких сервлетов, фильтров или прослушивателей. Spring использует файл javax.servlet.ServletContainerInitializer для инициализации экземпляра класса ServletContainerInitializer. Файл содержит ссылку на класс SpringServletContainerInitializer.

SpringServletContainerInitializer является ServletContainerInitializer, поэтому он получает ServletContext при запуске. Цель SpringServletContainerInitializer - передать servletContext более дружественному для разработчика WebApplicationInitializer, чтобы можно было добавлять сервлеты, такие как Springs DispatcherServlet, который является фронт-контроллером который направляет входящие запросы на другие контроллеры. (См. spring-framework-reference о том, как настроить DispatcherServlet для Spring.)

Spring MVC не предоставляет конкретную реализацию WebApplicationInitializer, только несколько абстрактных классов, так что вы можете контролировать процесс загрузки. В случае Spring Boot предусмотрена конкретная реализация: SpringApplicationWebApplicationInitializer для уменьшения количества кода шаблона.

Дополнительная информация

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...