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.

To see the execution order of each 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.
Be careful when registering 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.

Most often, you do not need to know about these implementation classes. Most applications are configured automatically, and the corresponding 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 to server.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.

See class 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:

Properties
server.servlet.session.cookie.same-site=none
Yaml
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.*.

Java

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.*");
    }
}
Kotlin

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:

Java

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);
    }
}
Kotlin

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:

Java

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()));
    }
}
Kotlin

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.

Automatically configured configuration modules are still applied to the custom factory, so use this option with caution.

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.