Servlet
, Filter
, ServletContextListener
and the other listeners supported by the
Servlet spec can be added to your application as @Bean
definitions. Be very careful that
they don’t cause eager initialization of too many other beans because they have to be
installed in the container very early in the application lifecycle (e.g. it’s not a good
idea to have them depend on your DataSource
or JPA configuration). You can work around
restrictions like that by initializing them lazily when first used instead of on
initialization.
In the case of Filters
and Servlets
you can also add mappings and init parameters by
adding a FilterRegistrationBean
or ServletRegistrationBean
instead of or as well as
the underlying component.
In a standalone application the main HTTP port defaults to 8080
, but can be set with
server.port
(e.g. in application.properties
or as a System property). Thanks to
relaxed binding of Environment
values you can also use SERVER_PORT
(e.g. as an OS
environment variable).
To switch off the HTTP endpoints completely, but still create a WebApplicationContext
,
use server.port=-1
(this is sometimes useful for testing).
For more details look at Section 24.2.3, “Customizing embedded servlet containers”
in the ‘Spring Boot features’ section, or the
ServerProperties
source
code.
To scan for a free port (using OS natives to prevent clashes) use server.port=0
.
You can access the port the server is running on from log output or from the
EmbeddedWebApplicationContext
via its EmbeddedServletContainer
. The best way to get
that and be sure that it has initialized is to add a @Bean
of type
ApplicationListener<EmbeddedServletContainerInitializedEvent>
and pull the container
out of the event when it is published.
A useful practice for use with @IntegrationTests
is to set server.port=0
and then inject the actual (‘local’) port as a @Value
. For example:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SampleDataJpaApplication.class) @WebAppConfiguration @IntegrationTest("server.port:0") public class CityRepositoryIntegrationTests { @Autowired EmbeddedWebApplicationContext server; @Value("${local.server.port}") int port; // ... }
SSL can be configured declaratively by setting the various server.ssl.*
properties,
typically in application.properties
or application.yml
. For example:
server.port = 8443 server.ssl.key-store = classpath:keystore.jks server.ssl.key-store-password = secret server.ssl.key-password = another-secret
See Ssl
for details of all of the
supported properties.
Note | |
---|---|
Tomcat requires the key store (and trust store if you’re using one) to be directly accessible on the filesystem, i.e. it cannot be read from within a jar file. |
Generally you can follow the advice from
Section 58.7, “Discover built-in options for external properties” about
@ConfigurationProperties
(ServerProperties
is the main one here), but also look at
EmbeddedServletContainerCustomizer
and various Tomcat-specific *Customizers
that you
can add in one of those. The Tomcat APIs are quite rich so once you have access to the
TomcatEmbeddedServletContainerFactory
you can modify it in a number of ways. Or the
nuclear option is to add your own TomcatEmbeddedServletContainerFactory
.
Add a org.apache.catalina.connector.Connector
to the
TomcatEmbeddedServletContainerFactory
which can allow multiple connectors, e.g. an HTTP and
HTTPS connector:
@Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); tomcat.addAdditionalTomcatConnectors(createSslConnector()); return tomcat; } private Connector createSslConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); try { File keystore = new ClassPathResource("keystore").getFile(); File truststore = new ClassPathResource("keystore").getFile(); connector.setScheme("https"); connector.setSecure(true); connector.setPort(8443); protocol.setSSLEnabled(true); protocol.setKeystoreFile(keystore.getAbsolutePath()); protocol.setKeystorePass("changeit"); protocol.setTruststoreFile(truststore.getAbsolutePath()); protocol.setTruststorePass("changeit"); protocol.setKeyAlias("apitester"); return connector; } catch (IOException ex) { throw new IllegalStateException("can't access keystore: [" + "keystore" + "] or truststore: [" + "keystore" + "]", ex); } }
Spring Boot will automatically configure Tomcat’s RemoteIpValve
if you enable it. This
allows you to transparently use the standard x-forwarded-for
and x-forwarded-proto
headers that most front-end proxy servers add. The valve is switched on by setting one or
both of these properties to something non-empty (these are the conventional values used by
most proxies, and if you only set one the other will be set automatically):
server.tomcat.remote_ip_header=x-forwarded-for server.tomcat.protocol_header=x-forwarded-proto
If your proxy uses different headers you can customize the valve’s configuration by adding
some entries to application.properties
, e.g.
server.tomcat.remote_ip_header=x-your-remote-ip-header server.tomcat.protocol_header=x-your-protocol-header
The valve is also configured with a default regular expression that matches internal
proxies that are to be trusted. By default, IP addresses in 10/8, 192.168/16, 169.254/16
and 127/8 are trusted. You can customize the valve’s configuration by adding an entry
to application.properties
, e.g.
server.tomcat.internal_proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3}
Note | |
---|---|
The double backslashes are only required when you’re using a properties file for
configuration. If you are using YAML, single backslashes are sufficient and a value
that’s equivalent to the one shown above would be |
Alternatively, you can take complete control of the configuration of the RemoteIpValve
by configuring and adding it in a TomcatEmbeddedServletContainerFactory
bean.
The Spring Boot starters (spring-boot-starter-web
in particular) use Tomcat as an
embedded container by default. You need to exclude those dependencies and include the
Jetty one instead. Spring Boot provides Tomcat and Jetty dependencies bundled together
as separate starters to help make this process as easy as possible.
Example in Maven:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
Example in Gradle:
configurations { compile.exclude module: "spring-boot-starter-tomcat" } dependencies { compile("org.springframework.boot:spring-boot-starter-web:1.1.12.RELEASE") compile("org.springframework.boot:spring-boot-starter-jetty:1.1.12.RELEASE") // ... }
Generally you can follow the advice from
Section 58.7, “Discover built-in options for external properties” about
@ConfigurationProperties
(ServerProperties
is the main one here), but also look at
EmbeddedServletContainerCustomizer
. The Jetty APIs are quite rich so once you have
access to the JettyEmbeddedServletContainerFactory
you can modify it in a number
of ways. Or the nuclear option is to add your own JettyEmbeddedServletContainerFactory
.
Tomcat 8 works with Spring Boot, but the default is to use Tomcat 7 (so we can support Java 1.6 out of the box). You should only need to change the classpath to use Tomcat 8 for it to work. For example, using the starter poms in Maven:
<properties> <tomcat.version>8.0.8</tomcat.version> </properties> <dependencies> ... <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ... </dependencies>
change the classpath to use Tomcat 8 for it to work.
Jetty 9 works with Spring Boot, but the default is to use Jetty 8 (so we can support Java 1.6 out of the box). You should only need to change the classpath to use Jetty 9 for it to work.
If you are using the starter poms and parent you can just add the Jetty starter and change the version properties, e.g. for a simple webapp or service:
<properties> <java.version>1.7</java.version> <jetty.version>9.1.0.v20131115</jetty.version> <servlet-api.version>3.1.0</servlet-api.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> </dependencies>
If you want to use @ServerEndpoint
in a Spring Boot application that used an embedded
container, you must declare a single ServerEndpointExporter
@Bean
:
@Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }
This bean will register any @ServerEndpoint
annotated beans with the underlying
WebSocket container. When deployed to a standalone servlet container this role is
performed by a servlet container initializer and the ServerEndpointExporter
bean is
not required.