For servlet applications, Spring Boot provides support for built-in servers Tomcat, Jetty, and Undertow . Most developers use an appropriate "starter" to get a fully configured instance. By default, the built-in server listens for HTTP requests on port 8080
.
Servlets, filters, and listeners
When using the built-in servlet container, you can register servlets, filters, and any listeners (such as HttpSessionListener
) from the servlet specification, either using Spring beans or crawling servlet components.
Registering servlets, filters, and listeners as Spring beans
Any instance of a Servlet
, Filter
, or *Listener
servlet that is a Spring bean is registered with the embedded container. This can be especially useful if you need to reference a value from application.properties
during configuration.
By default, if a context contains only one servlet, it is mapped to /
. In case of multiple servlet beans, the bean name is used as a path prefix. Filters are mapped to /*
.
If convention-based mapping is not flexible enough, you can use the ServletRegistrationBean
, FilterRegistrationBean
and ServletListenerRegistrationBean
for complete control.
Typically, the filter bean need not be ordered. If a specific ordering is required, then the Filter
must be annotated with the @Order
annotation or implemented as a Ordered
class. You cannot configure the order of a Filter
by annotating its bean method with the @Order
annotation. If you cannot modify the Filter
class to add the @Order
annotation or implement the Ordered
class, you must define a FilterRegistrationBean
for Filter
and set the order of the registration bean using the setOrder(int)
method. Avoid configuring a filter that reads the request body by Ordered.HIGHEST_PRECEDENCE
, as this may conflict with your application's character encoding configuration. If a servlet filter wraps a request, its configured execution order must be less than or equal to OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER
.
Filter
in the application, enable debug-level logging for the web logging group (
logging.level.web=debug
). Details of registered filters, including their order and URL patterns, will be logged on initial startup.
Filter beans
because they are instantiated very early in the application lifecycle. If you need to register a
Filter
that interacts with other beans, use a
DelegatingFilterProxyRegistrationBean
instead.
Initializing a Servlet Context
Built-in Servlet Containers do not directly execute the servlet 3.0+ interface called javax.servlet.ServletContainerInitializer
or the org.springframework.web.WebApplicationInitializer
interface from Spring. This is a deliberate design decision to reduce the risk that third-party libraries designed to run inside a war file may break Spring Boot applications.
If you want to initialize a servlet context in a Spring Boot application, you must register the bean which implements the org.springframework.boot.web.servlet.ServletContextInitializer
interface. The single onStartup
method provides access to the ServletContext
and, if necessary, can easily be used as an adapter to an existing WebApplicationInitializer
.
Scanning for servlets, filters, and listeners
When using a built-in container, automatically register classes marked with the @WebServlet
, @WebFilter
and @WebListener
annotations, can be activated using the @ServletComponentScan
annotation.
@ServletComponentScan
does not work in a standalone container, where the container's built-in discovery mechanisms are used instead.
The ServletWebServerApplicationContext
Internally, Spring Boot uses a different type of ApplicationContext
to support the embedded servlet container. ServletWebServerApplicationContext
is a special type of WebApplicationContext
that bootstraps itself by looking up a single ServletWebServerFactory
bean. Usually TomcatServletWebServerFactory
, JettyServletWebServerFactory
or UndertowServletWebServerFactory
are automatically configured.
ApplicationContext
and
ServletWebServerFactory
are created without your intervention.
In the embedded container configuration, the ServletContext
is set to as a server startup element that occurs during application context initialization. Because of this, beans in ApplicationContext
cannot be reliably initialized using ServletContext
. One way to work around this limitation is to implement ApplicationContext
as a bean dependency and only call ServletContext
when necessary. Another way is to use a callback immediately after the server starts. This can be done using an ApplicationListener
that listens to the ApplicationStartedEvent
like this:
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();
}
}
Personalizing settings for built-in servlet containers
General settings for a servlet container can be configured using the Environment
properties from Spring. Typically, properties are defined in the application.properties
or application.yaml
file.
General server settings include:
Network parameters: port for listening to incoming HTTP requests (
server.port
), interface address for binding toserver.address
, and so on.Session parameters: whether the session is stored for a long time (
server.servlet.session.persistent
), session waiting time (server.servlet.session.timeout
), session data location (server.servlet.session.store-dir
) and session cookie configuration (server.servlet.session.cookie.*
).Error management: error page location (
server.error.path
) and so on.SSL
HTTP compression
Spring Boot takes all necessary measures to provide access to as many general settings, but this is not always possible. In such cases, specialized namespaces provide server-specific settings (see server.tomcat
and server.undertow
). For example, access logs can be configured to take into account the specific features of the embedded servlet container.
ServerProperties
.
SameSite attribute for cookies
Web browsers can use the SameSite attribute
for cookies, to control whether and how cookies are passed on cross-site requests. The attribute is especially relevant to modern web browsers, which have begun to change the default value used when the attribute is missing.
If you want to change the SameSite
attribute of your session cookie, you can use the property server.servlet.session.cookie.same-site
. This property is supported by automatically configured Tomcat, Jetty and Undertow servers. It is also used to configure SessionRepository
beans based on Session servlets in Spring.
For example, if you want a session cookie to have a SameSite
attribute whose value is None
, then you can add the following code to the application.properties
or application.yaml
file:
server.servlet.session.cookie.same-site=none
server:
servlet:
session:
cookie:
same-site: "none"
If you want to change the SameSite
attribute for other cookies added to HttpServletResponse
, you can use CookieSameSiteSupplier
. CookieSameSiteSupplier
is passed to Cookie
and can return SameSite
or null
.
There are a number of factory helpers and filtering methods that can be used to quickly find specific cookies. For example, adding the following bean will automatically apply SameSite
from Lax
to all cookies with a name matching the regular expression 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.*")
}
}
Programmatically personalize settings
If you need to programmatically configure a built-in servlet container, you can register a Spring bean that implements the WebServerFactoryCustomizer
interface. WebServerFactoryCustomizer
provides access to the ConfigurableServletWebServerFactory
factory, which includes many setters. The following example shows how to configure a port programmatically:
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
and UndertowServletWebServerFactory
are special variants of ConfigurableServletWebServerFactory
that have additional setters for Tomcat, Jetty and Undertow respectively. The following example shows how to configure a TomcatServletWebServerFactory
that provides access to Tomcat-related configuration options:
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() })
}
}
Direct personalization of ConfigurableServletWebServerFactory settings
In more complex use cases that require an extension from ServletWebServerFactory
, you can open a bean of this type yourself.
Setters are provided for many configuration parameters. There are also several "interceptors" for protected methods if you need to do something more unusual. For details, see documentation in source code.
JSP Limitations
When running a Spring Boot application that uses the built-in servlet container (and is packaged as an executable archive), there are some limitations to the JSP support facilities.
With Jetty and Tomcat everything should work if you use war file packaging. The executable war file will work when run via
java -jar
and will also be deployed to any standard container. JSP pages are not supported when using an executable jar file.Undertow does not support JSP pages.
Creating a custom page
error.jsp
does not override the default error handling view. Custom error pages should be used instead.
GO TO FULL VERSION