Введение
В 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 .