Для сервлет-приложений Spring Boot предусматривает поддержку встроенных серверов Tomcat, Jetty, и Undertow. Большинство разработчиков используют соответствующий "стартер" для получения полностью сконфигурированного экземпляра. По умолчанию встроенный сервер прослушивает HTTP-запросы через порт 8080
.
Сервлеты, фильтры и слушатели
При использовании встроенного контейнера сервлетов можно зарегистрировать сервлеты, фильтры и любые слушатели (такие как HttpSessionListener
) из спецификации сервлетов, либо используя бины Spring, либо осуществляя сканирование компонентов сервлетов.
Регистрация сервлетов, фильтров и слушателей в качестве бинов Spring
Любой экземпляр Servlet
, Filter
или *Listener
сервлета, который является бином Spring, регистрируется во встроенном контейнере. Это может быть особенно удобно, если нужно сослаться на значение из application.properties
во время конфигурирования.
По умолчанию, если контекст содержит только один сервлет, он отображается на /
. В случае нескольких сервлет-бинов имя бина используется в качестве префикса пути. Фильтры отображаются на /*
.
Если отображение на основе соглашений недостаточно гибкое, то можно использовать классы ServletRegistrationBean
, FilterRegistrationBean
и ServletListenerRegistrationBean
для полного контроля.
Как правило, бин-фильтр можно не упорядочивать. Если требуется определенное упорядочивание, то необходимо аннотировать Filter
с помощью аннотации @Order
или реализовать его как класс Ordered
. Сконфигурировать порядок Filter
, аннотировав его метод бина с помощью аннотации @Order
, нельзя. Если нельзя изменить класс Filter
, чтобы добавить аннотацию @Order
или реализовать класс Ordered
, необходимо определить FilterRegistrationBean
для Filter
и установить порядок регистрационного бина с помощью метода setOrder(int)
. Избегайте конфигурирования фильтра, который читает тело запроса по Ordered.HIGHEST_PRECEDENCE
, поскольку это может противоречить конфигурации кодировки символов вашего приложения. Если фильтр сервлета обертывает запрос, его сконфигурированный порядок выполнения должен быть меньше или равняться OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER
.
Filter
в приложении, активируйте логирование на уровне отладки для группы веб-журналирования (logging.level.web=debug
). Подробная информация о зарегистрированных фильтрах, включая их порядок и шаблоны URL-адресов, будет регистрироваться при начальном запуске.Filter
, поскольку их экземпляры создаются на очень ранних стадиях жизненного цикла приложения. Если необходимо зарегистрировать Filter
, который взаимодействует с другими бинами, используйте вместо него DelegatingFilterProxyRegistrationBean
.Инициализация контекста сервлетов
Встроенные контейнеры сервлетов не выполняют напрямую интерфейс servlet 3.0+ под названием javax.servlet.ServletContainerInitializer
или интерфейс org.springframework.web.WebApplicationInitializer
из Spring. Это преднамеренное проектное решение, призванное снизить риск того, что сторонние библиотеки, разработанные для выполнения внутри war-файла, могут сломать приложения Spring Boot.
Если требуется выполнить инициализацию контекста сервлетов в приложении Spring Boot, необходимо зарегистрировать бин, который реализует интерфейс org.springframework.boot.web.servlet.ServletContextInitializer
. Единственный метод onStartup
обеспечивает доступ к ServletContext
и, при необходимости, может быть легко использован в качестве адаптера к существующему WebApplicationInitializer
.
Сканирование на предмет сервлетов, фильтров и слушателей
При использовании встроенного контейнера автоматическую регистрацию классов, помеченных аннотациями @WebServlet
, @WebFilter
и @WebListener
, можно активировать с помощью аннотации @ServletComponentScan
.
@ServletComponentScan
не работает в автономном контейнере, где вместо неё используются встроенные механизмы обнаружения для контейнера.The ServletWebServerApplicationContext
С точки зрения внутреннего устройства Spring Boot использует другой тип ApplicationContext
для поддержки встроенного контейнера сервлетов. ServletWebServerApplicationContext
– это особый тип WebApplicationContext
, который самозагружается путем поиска единственного бина ServletWebServerFactory
. Обычно автоматически конфигурируются TomcatServletWebServerFactory
, JettyServletWebServerFactory
или UndertowServletWebServerFactory
.
ApplicationContext
и ServletWebServerFactory
создаются без вашего участия.В конфигурации встроенного контейнера ServletContext
устанавливается в качестве элемента запуска сервера, который происходит во время инициализации контекста приложения. Ввиду этого бины в ApplicationContext
нельзя надежно инициализировать с помощью ServletContext
. Один из способов обхода этого ограничения – внедрение ApplicationContext
в качестве зависимости бина и обращение к ServletContext
только при необходимости. Другой способ – использовать обратный вызов сразу после запуска сервера. Это можно сделать с помощью ApplicationListener
, который прослушивает ApplicationStartedEvent
следующим образом:
import javax.servlet.ServletContext;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.web.context.WebApplicationContext;
public class MyDemoBean implements ApplicationListener<ApplicationStartedEvent> {
private ServletContext servletContext;
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
this.servletContext = ((WebApplicationContext) applicationContext).getServletContext();
}
}
Персонализация настроек встроенных контейнеров сервлетов
Общие параметры контейнера сервлетов можно сконфигурировать с помощью свойств Environment
из Spring. Как правило, свойства определяются в файле application.properties
или application.yaml
.
Общие параметры сервера включают:
-
Параметры сети: порт для прослушивания входящих HTTP-запросов (
server.port
), адрес интерфейса для привязки кserver.address
, и так далее. -
Параметры сессии: хранится ли сессия длительно (
server.servlet.session.persistent
), время ожидании сессии (server.servlet.session.timeout
), местоположение данных сессии (server.servlet.session.store-dir
) и cookie-конфигурация сессии (server.servlet.session.cookie.*
). -
Управление ошибками: местоположение страницы ошибок (
server.error.path
) и так далее. -
SSL
-
HTTP-сжатие
Spring Boot предпринимает все необходимые меры, чтобы открывать доступ к как можно большему количеству общих настроек, но это не всегда возможно. В таких случаях специализированными пространствами имен предусмотрены специфические для сервера настройки (см. server.tomcat
и server.undertow
). Например, журналы доступа можно сконфигурировать с учетом специфических особенностей встроенного контейнера сервлетов.
ServerProperties
.Атрибут SameSite для файлов cookie
Веб-браузеры могут использовать атрибут SameSite
для файлов cookie, чтобы управлять тем, передаются ли вообще файлы cookie при межсайтовых запросах и каким образом. Атрибут особенно актуален для современных веб-браузеров, которые начали изменять значение по умолчанию, используемое при отсутствии атрибута.
Если вы хотите изменить атрибут SameSite
вашего сессионного файла cookie, то можете использовать свойство server.servlet.session.cookie.same-site
. Это свойство поддерживается автоматически сконфигурированными серверами Tomcat, Jetty и Undertow. Он также используется для настройки бинов SessionRepository
на основе сервлетов Сессия в Spring.
Например, если нужно, чтобы сессионный файл cookie имел атрибут SameSite
, значение которого равно None
, то можно добавить следующий код в файл application.properties
или application.yaml
:
server.servlet.session.cookie.same-site=none
server:
servlet:
session:
cookie:
same-site: "none"
Если вы хотите изменить атрибут SameSite
для других файлов cookie, добавленных в HttpServletResponse
, то можете использовать CookieSameSiteSupplier
. CookieSameSiteSupplier
передается Cookie
и может вернуть значение SameSite
или null
.
Существует ряд вспомогательных фабричных и фильтрационных методов, которые можно использовать для быстрого поиска определенных файлов cookie. Например, добавление следующего бина автоматически применит SameSite
из Lax
для всех файлов cookie с именем, соответствующим регулярному выражению myapp.*
.
import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MySameSiteConfiguration {
@Bean
public CookieSameSiteSupplier applicationCookieSameSiteSupplier() {
return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*");
}
}
import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
class MySameSiteConfiguration {
@Bean
fun applicationCookieSameSiteSupplier(): CookieSameSiteSupplier {
return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*")
}
}
Программная персонализация настроек
Если необходимо программно сконфигурировать встроенный контейнер сервлетов, то можно зарегистрировать бин Spring, который реализует интерфейс WebServerFactoryCustomizer
. WebServerFactoryCustomizer
предоставляет доступ к фабрике ConfigurableServletWebServerFactory
, которая включает в себя множество сеттеров. В следующем примере показана программная настройка порта:
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory server) {
server.setPort(9000);
}
}
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory
import org.springframework.stereotype.Component
@Component
class MyWebServerFactoryCustomizer : WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
override fun customize(server: ConfigurableServletWebServerFactory) {
server.setPort(9000)
}
}
TomcatServletWebServerFactory
, JettyServletWebServerFactory
и UndertowServletWebServerFactory
– это специальные варианты ConfigurableServletWebServerFactory
, которые имеют дополнительные сеттеры для Tomcat, Jetty и Undertow соответственно. В следующем примере показано, как настроить TomcatServletWebServerFactory
, который предоставляет доступ к связанным с Tomcat параметрам конфигурации:
import java.time.Duration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class MyTomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory server) {
server.addConnectorCustomizers((connector) -> connector.setAsyncTimeout(Duration.ofSeconds(20).toMillis()));
}
}
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.stereotype.Component
import java.time.Duration
@Component
class MyTomcatWebServerFactoryCustomizer : WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
override fun customize(server: TomcatServletWebServerFactory) {
server.addConnectorCustomizers({ connector -> connector.asyncTimeout = Duration.ofSeconds(20).toMillis() })
}
}
Прямая персонализация настроек ConfigurableServletWebServerFactory
В более сложных случаях применения, требующих расширения из ServletWebServerFactory
, можно самостоятельно открыть бин такого типа.
Для многих параметров конфигурации предусмотрены сеттеры. Также предусмотрено несколько "перехватчиков" для защищенных методов, если требуется сделать что-то более неординарное. Подробнее см. документирование в исходном коде.
Ограничения JSP
При запуске приложения Spring Boot, которое использует встроенный контейнер сервлетов (и упаковано как исполняемый архив), существуют некоторые ограничения средств поддержки JSP.
-
С Jetty и Tomcat все должно работать, если вы используете упаковывание в war-файл. Исполняемый war-файл будет работать при запуске через
java -jar
, а также будет развертываться в любом стандартном контейнере. Страницы JSP не поддерживаются при использовании исполняемого jar-файла. -
Undertow не поддерживает страницы JSP.
-
Создание кастомной страницы
error.jsp
не переопределяет представление по умолчанию для обработки ошибок. Вместо этого следует использовать кастомные страницы ошибок.