Embedded servlet containers
73. Embedded servlet containers
73.1 Add a Servlet, Filter or Listener to an application
There are two ways to add Servlet
, Filter
, ServletContextListener
and the other listeners supported by the Servlet spec to your application. You can either provide Spring beans for them, or enable scanning for Servlet components.
73.1.1 Add a Servlet, Filter or Listener using a Spring bean
To add a Servlet
, Filter
, or Servlet *Listener
provide a @Bean
definition for it. This can be very useful when you want to inject configuration or dependencies. However, you must 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.
If no If you are migrating a filter that has no @Bean |
Disable registration of a Servlet or Filter
As described above any Servlet
or Filter
beans will be registered with the servlet container automatically. To disable registration of a particular Filter
or Servlet
bean create a registration bean for it and mark it as disabled. For example:
@Bean
public FilterRegistrationBean registration(MyFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
73.1.2 Add Servlets, Filters, and Listeners using classpath scanning
@WebServlet
, @WebFilter
, and @WebListener
annotated classes can be automatically registered with an embedded servlet container by annotating a @Configuration
class with @ServletComponentScan
and specifying the package(s) containing the components that you want to register. By default, @ServletComponentScan
will scan from the package of the annotated class.
73.2 Change the HTTP port
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 27.3.4, “Customizing embedded servlet containers” in the ‘Spring Boot features’ section, or the ServerProperties
source code.
73.3 Use a random unassigned HTTP port
To scan for a free port (using OS natives to prevent clashes) use server.port=0
.
73.4 Discover the HTTP port at runtime
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.
Tests that use @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
can also inject the actual port into a field using the @LocalServerPort
annotation. For example:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests { @Autowired
EmbeddedWebApplicationContext server; @LocalServerPort
int port; // ... }
|
73.5 Configure SSL
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.
Using configuration like the example above means the application will no longer support plain HTTP connector at port 8080. Spring Boot doesn’t support the configuration of both an HTTP connector and an HTTPS connector via application.properties
. If you want to have both then you’ll need to configure one of them programmatically. It’s recommended to use application.properties
to configure HTTPS as the HTTP connector is the easier of the two to configure programmatically. See the spring-boot-sample-tomcat-multi-connectors
sample project for an example.
73.6 Configure Access Logging
Access logs can be configured for Tomcat and Undertow via their respective namespaces.
For instance, the following logs access on Tomcat with a custom pattern.
server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
The default location for logs is a |
Access logging for undertow can be configured in a similar fashion
server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms)
Logs are stored in a logs
directory relative to the working directory of the application. This can be customized via server.undertow.accesslog.directory
.
73.7 Use behind a front-end proxy server
Your application might need to send 302
redirects or render content with absolute links back to itself. When running behind a proxy, the caller wants a link to the proxy, and not to the physical address of the machine hosting your app. Typically such situations are handled via a contract with the proxy, which will add headers to tell the back end how to construct links to itself.
If the proxy adds conventional X-Forwarded-For
and X-Forwarded-Proto
headers (most do this out of the box) the absolute links should be rendered correctly as long as server.use-forward-headers
is set to true
in your application.properties
.
If your application is running in Cloud Foundry or Heroku the |
73.7.1 Customize Tomcat’s proxy configuration
If you are using Tomcat you can additionally configure the names of the headers used to carry “forwarded” information:
server.tomcat.remote-ip-header=x-your-remote-ip-header
server.tomcat.protocol-header=x-your-protocol-header
Tomcat 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}
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 |
You can trust all proxies by setting the |
You can take complete control of the configuration of Tomcat’s RemoteIpValve
by switching the automatic one off (i.e. set server.use-forward-headers=false
) and adding a new valve instance in a TomcatEmbeddedServletContainerFactory
bean.
73.8 Configure Tomcat
Generally you can follow the advice from Section 72.8, “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
.
73.9 Enable Multiple Connectors with Tomcat
Add a org.apache.catalina.connector.Connector
to the TomcatEmbeddedServletContainerFactory
which can allow multiple connectors, e.g. 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);
}
}
73.10 Use Tomcat’s LegacyCookieProcessor
The embedded Tomcat used by Spring Boot does not support "Version 0" of the Cookie format out of the box, and you may see the following error:
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
If at all possible, you should consider updating your code to only store values compliant with later Cookie specifications. If, however, you’re unable to change the way that cookies are written, you can instead configure Tomcat to use a LegacyCookieProcessor
. To switch to the LegacyCookieProcessor
use anEmbeddedServletContainerCustomizer
bean that adds a TomcatContextCustomizer
:
@Bean
public EmbeddedServletContainerCustomizer cookieProcessorCustomizer() {
return new EmbeddedServletContainerCustomizer() { @Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addContextCustomizers(new TomcatContextCustomizer() { @Override
public void customize(Context context) {
context.setCookieProcessor(new LegacyCookieProcessor());
} });
}
} };
}
73.11 Use Jetty instead of Tomcat
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.5.3.RELEASE")
compile("org.springframework.boot:spring-boot-starter-jetty:1.5.3.RELEASE")
// ...
}
73.12 Configure Jetty
Generally you can follow the advice from Section 72.8, “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
.
73.13 Use Undertow instead of Tomcat
Using Undertow instead of Tomcat is very similar to using Jetty instead of Tomcat. You need to exclude the Tomcat dependencies and include the Undertow starter instead.
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-undertow</artifactId>
</dependency>
Example in Gradle:
configurations {
compile.exclude module: "spring-boot-starter-tomcat"
} dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.5.3.RELEASE")
compile("org.springframework.boot:spring-boot-starter-undertow:1.5.3.RELEASE")
// ...
}
73.14 Configure Undertow
Generally you can follow the advice from Section 72.8, “Discover built-in options for external properties” about @ConfigurationProperties
(ServerProperties
and ServerProperties.Undertow
are the main ones here), but also look at EmbeddedServletContainerCustomizer
. Once you have access to theUndertowEmbeddedServletContainerFactory
you can use an UndertowBuilderCustomizer
to modify Undertow’s configuration to meet your needs. Or the nuclear option is to add your own UndertowEmbeddedServletContainerFactory
.
73.15 Enable Multiple Listeners with Undertow
Add an UndertowBuilderCustomizer
to the UndertowEmbeddedServletContainerFactory
and add a listener to the Builder
:
@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() { @Override
public void customize(Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
} });
return factory;
}
73.16 Use Tomcat 7.x or 8.0
Tomcat 7 & 8.0 work with Spring Boot, but the default is to use Tomcat 8.5. If you cannot use Tomcat 8.5 (for example, because you are using Java 1.6) you will need to change your classpath to reference a different version.
73.16.1 Use Tomcat 7.x or 8.0 with Maven
If you are using the starters and parent you can change the Tomcat version property and additionally import tomcat-juli
. E.g. for a simple webapp or service:
<properties>
<tomcat.version>7.0.59</tomcat.version>
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<version>${tomcat.version}</version>
</dependency>
...
</dependencies>
73.16.2 Use Tomcat 7.x or 8.0 with Gradle
With Gradle, you can change the Tomcat version by setting the tomcat.version
property and then additionally include tomcat-juli
:
ext['tomcat.version'] = '7.0.59'
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
compile group:'org.apache.tomcat', name:'tomcat-juli', version:property('tomcat.version')
}
73.17 Use Jetty 9.2
Jetty 9.2 works with Spring Boot, but the default is to use Jetty 9.3. If you cannot use Jetty 9.3 (for example, because you are using Java 7) you will need to change your classpath to reference Jetty 9.2.
73.17.1 Use Jetty 9.2 with Maven
If you are using the starters and parent you can just add the Jetty starter and override the jetty.version
property:
<properties>
<jetty.version>9.2.17.v20160517</jetty.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>
73.17.2 Use Jetty 9.2 with Gradle
You can set the jetty.version
property. For example, for a simple webapp or service:
ext['jetty.version'] = '9.2.17.v20160517'
dependencies {
compile ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile ('org.springframework.boot:spring-boot-starter-jetty')
}
73.18 Use Jetty 8
Jetty 8 works with Spring Boot, but the default is to use Jetty 9.3. If you cannot use Jetty 9.3 (for example, because you are using Java 1.6) you will need to change your classpath to reference Jetty 8. You will also need to exclude Jetty’s WebSocket-related dependencies.
73.18.1 Use Jetty 8 with Maven
If you are using the starters and parent you can just add the Jetty starter with the required WebSocket exclusion and change the version properties, e.g. for a simple webapp or service:
<properties>
<jetty.version>8.1.15.v20140411</jetty.version>
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.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>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
73.18.2 Use Jetty 8 with Gradle
You can set the jetty.version
property and exclude the WebSocket dependency, e.g. for a simple webapp or service:
ext['jetty.version'] = '8.1.15.v20140411'
dependencies {
compile ('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile ('org.springframework.boot:spring-boot-starter-jetty') {
exclude group: 'org.eclipse.jetty.websocket'
}
}
73.19 Create WebSocket endpoints using @ServerEndpoint
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.
73.20 Enable HTTP response compression
HTTP response compression is supported by Jetty, Tomcat, and Undertow. It can be enabled via application.properties
:
server.compression.enabled=true
By default, responses must be at least 2048 bytes in length for compression to be performed. This can be configured using the server.compression.min-response-size
property.
By default, responses will only be compressed if their content type is one of the following:
text/html
text/xml
text/plain
text/css
This can be configured using the server.compression.mime-types
property.
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-embedded-servlet-containers
Embedded servlet containers的更多相关文章
- Tomcat vs. Jetty vs. Undertow: Comparison of Spring Boot Embedded Servlet Containers
原文地址:https://examples.javacodegeeks.com/enterprise-java/spring/tomcat-vs-jetty-vs-undertow-compariso ...
- 1.端口被占用问题:Embedded servlet container failed to start. Port 8097 was already in use.
1.端口被占用问题:Embedded servlet container failed to start. Port 8097 was already in use.netstat -anonetst ...
- SpringBoot 配置 Servlet、Filter、Listener
SpringBoot 配置 Servlet.Filter.Listener 在SpringBoot应用中,嵌入式的 Servlet 3.0+ 容器不会直接使用 ServletContainerInit ...
- spring mvc DispatcherServlet详解之前传---FrameworkServlet
做项目时碰到Controller不能使用aop进行拦截,从网上搜索得知:使用spring mvc 启动了两个context:applicationContext 和WebapplicationCont ...
- 深入学习微框架:Spring Boot - NO
http://blog.csdn.net/hengyunabc/article/details/50120001 Our primary goals are: Provide a radically ...
- 40. Testing Prev Part IV. Spring Boot features
40. Testing Spring Boot provides a number of utilities and annotations to help when testing your app ...
- spring-boot(三) HowTo
Spring Boot How To 1. 简介 本章节将回答一些常见的"我该怎么做"类型的问题,这些问题在我们使用spring Boot时经常遇到.这绝不是一个详尽的列表,但它覆 ...
- SpringBoot 之 MVC
SpringBoot MVC 和静态资源 首先,我们一定要搞清楚,mvc 配置和 static 配置的联系和区别. mvc 配置其实就是给 spring mvc 框架用的, 具体来说, 比如 @Req ...
- Spring Boot 容器选择 Undertow 而不是 Tomcat
Spring Boot 内嵌容器Undertow参数设置 配置项: # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动 ...
随机推荐
- jQuery的ajax使用
一:jQuery.ajax语法基础 jQuery.ajax([options]) 概述:通过 HTTP 请求加载远程数据. jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $. ...
- CentOS删除自带的java,安装新java
[root@localhost ~]# java -version java version "1.4.2″ gij (GNU libgcj) version 4.1.2 20071124 ...
- AES涉及的有限域乘法及字节填充方法
非常值得参考的是官方文档,它详细介绍了AES及其实验过程.博文AES加密算法的C++实现就是基于该文档的介绍及实现,是难得的一篇好文,故在本文最后会附上该文,以作备份. 还有很值得推荐的就是AES的 ...
- 【43】Activity的几种LaunchMode及使用场景
standard 模式 这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中.使用场景:大多数Activity. singleTop 模式 如果在任务的栈顶正好存在该A ...
- 关于webp图片格式初探
前言 不管是 PC 还是移动端,图片一直是流量大头,以苹果公司 Retina 产品为代表的高 PPI 屏对图片的质量提出了更高的要求,如何保证在图片的精细度不降低的前提下缩小图片体积,成为了一个有价值 ...
- javascript访问html元素的内容(2)
对于(1)中最后一个包装方式创建的是一个方法,我们必须以方法调用的方式来使用它,这和其他默认的以属性返回结果略有不同,如果有强迫症的童鞋有些伤不起,那么我们下面就把它实现为属性返回的方式: //chi ...
- 重定向和servlet生命周期
重定向(1)什么是重定向服务器通知浏览器向一个新的地址发送请求.注:可以发送一个302状态码和一个Location消息头.(该消息头包含了一个地址,称之为重定向地址),浏览器收到之后,会立即向重定向地 ...
- 浅析跨域的方法之一 JSONP
概念: 什么叫跨域? 同源策略:它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略. 所谓同源是指,域名,协议,端口相同. 同源的脚本才会被执行 ...
- 关闭ipv6的方法
公司研发反应,几台机器开了一些端口,但是访问一直不通. 检查后发现,发现服务开启的是ipv6的端口,所有首先想到的办法就是关闭ipv6. 关闭ipv6的方法有两种: 第一个是在内核配置文件修改配置(p ...
- element.dispatchEvent is not a function的解决
Firebug中的出错提示: element.dispatchEvent is not a function element.dispatchEvent(event); prototype.js (第 ...