嵌入式Web服务器
每个Spring Boot Web应用程序都包含一个嵌入式Web服务器。此功能会导致许多操作方法问题,包括如何更改嵌入式服务器以及如何配置嵌入式服务器。本节回答了这些问题。
使用其他Web服务器
许多Spring Boot启动器都包含默认的嵌入式容器。
- 对于servlet堆栈应用程序,
spring-boot-starter-web
包括Tomcatspring-boot-starter-tomcat
,但您可以使用spring-boot-starter-jetty
或spring-boot-starter-undertow
替代。 - 对于反应栈的应用,
spring-boot-starter-webflux
包括反应堆的Netty通过包括spring-boot-starter-reactor-netty
,但你可以使用spring-boot-starter-tomcat
,spring-boot-starter-jetty
或spring-boot-starter-undertow
代替。
切换到其他HTTP服务器时,除了包含所需的依赖项外,还需要排除默认依赖项。Spring Boot为HTTP服务器提供单独的启动程序,以帮助使此过程尽可能简单。
以下Maven示例显示如何排除Tomcat并为Spring MVC包含Jetty:
1 | <properties> |
Servlet API的版本已被覆盖,因为与Tomcat 9和Undertow 2.0不同,Jetty 9.4不支持Servlet 4.0。
以下Gradle示例显示如何排除Netty并包含Spring WebFlux的Undertow:
1 | configurations { |
spring-boot-starter-reactor-netty
需要使用WebClient
该类,因此即使您需要包含不同的HTTP服务器,也可能需要依赖Netty。
禁用Web服务器
如果您的类路径包含启动Web服务器所需的位,Spring Boot将自动启动它。要禁用此行为,请WebApplicationType
在您的配置中进行配置application.properties
,如以下示例所示:
1 | spring.main.web-application-type=none |
更改HTTP端口
在独立应用程序中,主HTTP端口默认为8080
但可以设置 server.port
(例如,application.properties
作为System属性或作为System属性)。由于轻松绑定Environment
值,您还可以使用SERVER_PORT
(例如,作为OS环境变量)。
要完全关闭HTTP端点但仍然创建一个WebApplicationContext
,请使用server.port=-1
。(这样做有时对测试很有用。)
有关更多详细信息,请参阅“ Spring Boot功能”部分中的“ 第29.4.4节”“自定义嵌入式Servlet容器”或 ServerProperties
源代码。
使用随机未分配的HTTP端口
要扫描一个空闲端口(使用OS本机来防止冲突),请使用server.port=0
。
在运行时发现HTTP端口
您可以从日志输出或ServletWebServerApplicationContext
通过其输出访问服务器正在运行的端口 WebServer
。获得它并确保它已被初始化的最佳方法是添加一个@Bean
类型, ApplicationListener<ServletWebServerInitializedEvent>
并在发布时将容器拉出事件。
使用的测试@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
还可以使用@LocalServerPort
注释将实际端口注入字段,如以下示例所示:
1 | (SpringJUnit4ClassRunner.class) |
@LocalServerPort
是一个元注释@Value("${local.server.port}")
。不要尝试在常规应用程序中注入端口。正如我们刚刚看到的那样,只有在容器初始化之后才设置该值。与测试相反,应用程序代码回调会尽早处理(在值实际可用之前)。
启用HTTP响应压缩
Jetty,Tomcat和Undertow支持HTTP响应压缩。它可以启用application.properties
,如下所示:
1 | server.compression.enabled=true |
默认情况下,响应必须至少为2048字节,才能执行压缩。您可以通过设置server.compression.min-response-size
属性来配置此行为 。
默认情况下,只有在内容类型为以下内容之一时才会压缩响应:
text/html
text/xml
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
您可以通过设置server.compression.mime-types
属性来配置此行为。
配置SSL
可以通过设置各种server.ssl.*
属性以声明方式配置SSL ,通常在application.properties
或中application.yml
。以下示例显示了在以下位置设置SSL属性application.properties
:
1 | server.port=8443 |
有关Ssl
所有支持的属性的详细信息,请参阅。
使用上述示例之类的配置意味着应用程序不再支持端口8080上的普通HTTP连接器.Spring Boot不支持HTTP连接器和HTTPS连接器的配置application.properties
。如果要同时使用两者,则需要以编程方式配置其中一个。我们建议使用 application.properties
配置HTTPS,因为HTTP连接器更容易以编程方式配置。有关spring-boot-sample-tomcat-multi-connectors
示例,请参阅 示例项目。
配置HTTP / 2
您可以使用server.http2.enabled
配置属性在Spring Boot应用程序中启用HTTP / 2支持 。此支持取决于所选的Web服务器和应用程序环境,因为JDK8不支持该协议。
Spring Boot不支持
h2c
HTTP / 2协议的明文版本。因此,您必须先配置SSL。
Undertow的HTTP / 2
从Undertow 1.4.0+开始,支持HTTP / 2,对JDK8没有任何额外要求。
Jetty的HTTP / 2
从Jetty 9.4.8开始,Conscrypt库也支持HTTP / 2 。要启用该支持,您的应用程序需要有两个额外的依赖项:org.eclipse.jetty:jetty-alpn-conscrypt-server
和org.eclipse.jetty.http2:http2-server
。
Tomcat的HTTP / 2
Spring Boot默认使用Tomcat 9.0.x,它在使用JDK 9或更高版本时支持HTTP / 2开箱即用。或者,如果libtcnative
库及其依赖项安装在主机操作系统上,则可以在JDK 8上使用HTTP / 2 。
必须使库文件夹(如果尚未可用)到JVM库路径。您可以使用JVM参数来完成此操作 -Djava.library.path=/usr/local/opt/tomcat-native/lib
。有关Tomcat官方文档的更多 信息。
在没有该本机支持的情况下在JDK 8上启动Tomcat 9.0.x会记录以下错误:
1 | ERROR 8787 --- [ main] o.a.coyote.http11.Http11NioProtocol : The upgrade handler [org.apache.coyote.http2.Http2Protocol] for [h2] only supports upgrade via ALPN but has beenconfigured for the ["https-jsse-nio-8443"] connector that does not support ALPN. |
此错误不是致命错误,应用程序仍以HTTP / 1.1 SSL支持启动。
Reactor Netty的HTTP / 2
在spring-boot-webflux-starter
默认情况下,反应堆的Netty作为服务器使用。可以使用JDK 9或更高版本的JDK支持为Reactor Netty配置HTTP / 2。对于JDK 8环境或最佳运行时性能,此服务器还支持具有本机库的HTTP / 2。要启用它,您的应用程序需要具有其他依赖项。
Spring Boot管理io.netty:netty-tcnative-boringssl-static
“超级jar” 的版本 ,包含所有平台的本机库。开发人员可以选择使用分类器仅导入所需的依赖项(请参阅Netty官方文档)。
配置Web服务器
通常,您应首先考虑使用众多可用配置键中的一个,并通过在您的application.properties
( application.yml
或环境等)中添加新条目来自定义您的Web服务器,请参阅“ 第77.8节”,“发现外部属性的内置选项” “) 。该server.*
命名空间是非常有用的在这里,它包括命名空间一样server.tomcat.*
,server.jetty.*
和其他人,了解特定服务器的功能。请参阅附录A,常见应用程序属性列表。
前面的部分介绍了许多常见用例,例如压缩,SSL或HTTP / 2。但是,如果您的用例不存在配置密钥,则应该查看 WebServerFactoryCustomizer
。您可以声明这样的组件并获得与您选择的服务器工厂相关的访问权限:您应该为所选服务器(Tomcat,Jetty,Reactor Netty,Undertow)和所选Web堆栈(Servlet或Reactive)选择变体。
以下示例适用于具有spring-boot-starter-web
(Servlet堆栈)的Tomcat :
1 |
|
另外Spring Boot提供:
服务器 | Servlet Stack | Reactive Stack |
---|---|---|
Tomcat的 | TomcatServletWebServerFactory |
TomcatReactiveWebServerFactory |
码头 | JettyServletWebServerFactory |
JettyReactiveWebServerFactory |
暗潮 | UndertowServletWebServerFactory |
UndertowReactiveWebServerFactory |
反应堆 | N / A | NettyReactiveWebServerFactory |
一旦您有权访问a WebServerFactory
,您通常可以向其添加定制器以配置特定部件,例如连接器,服务器资源或服务器本身 - 所有这些都使用特定于服务器的API。
作为最后的手段,您还可以声明自己的WebServerFactory
组件,它将覆盖Spring Boot提供的组件。在这种情况下,您不能再依赖server
命名空间中的配置属性。
向应用程序添加Servlet,Filter或Listener
在servlet堆栈应用程序中,即使用spring-boot-starter-web
,有两种方法可以向应用程序添加Servlet
,Filter
和ServletContextListener
,以及Servlet API支持的其他侦听器:
使用Spring Bean添加
要添加Servlet
,Filter
或servlet *Listener
使用的Spring bean,你必须提供一个@Bean
它的定义。当您想要注入配置或依赖项时,这样做非常有用。但是,您必须非常小心,它们不会导致太多其他bean的初始化,因为它们必须在应用程序生命周期的早期安装在容器中。(例如,让它们依赖于您的DataSource
或JPA配置并不是一个好主意。)您可以通过在首次使用而不是初始化时懒惰地初始化bean来解决此类限制。
在的情况下Filters
和Servlets
,还可以通过添加添加映射和初始化参数FilterRegistrationBean
或ServletRegistrationBean
代替或除了下面的部件。
如果
dispatcherType
在过滤器注册中指定了no ,REQUEST
则使用。这与Servlet规范的默认调度程序类型一致。
像任何其他Spring bean一样,您可以定义Servlet过滤器bean的顺序; 请务必检查“ 名为”将Servlet,过滤器和监听器注册为Spring Beans “部分。
禁用Servlet或过滤器的注册
正如前面所述,任何 Servlet
或Filter
豆与servlet容器自动注册。要禁用特定Filter
或Servlet
bean的注册,请为其创建注册Bean并将其标记为已禁用,如以下示例所示:
1 |
|
使用类路径扫描添加
@WebServlet
,@WebFilter
和带@WebListener
注释的类可以通过使用一个@Configuration
类注释@ServletComponentScan
并指定包含要注册的组件的包来自动注册嵌入式servlet容器。默认情况下,@ServletComponentScan
从带注释的类的包中进行扫描。
配置访问日志记录
以通过各自的命名空间为Tomcat,Undertow和Jetty配置访问日志。
例如,以下设置使用自定义模式在Tomcat上记录访问权限 。
1 | server.tomcat.basedir=my-tomcat |
日志存储在logs
相对于应用程序工作目录的目录中。您可以通过设置server.undertow.accesslog.directory
属性来自定义此位置 。
最后,Jetty的访问日志记录也可以配置如下:
1 | server.jetty.accesslog.enabled=true |
默认情况下,日志会重定向到System.err
。有关更多详细信息,请参阅 Jetty文档。
在前端代理服务器后面运行
您的应用程序可能需要发送302
重定向或使用绝对链接呈现内容。在代理后面运行时,调用者需要指向代理的链接,而不是托管应用程序的计算机的物理地址。通常,这种情况是通过与代理的合同来处理的,代理会添加标题以告诉后端如何构建自己的链接。
如果代理添加了常规X-Forwarded-For
和X-Forwarded-Proto
头文件(大多数代理服务器都这样做),则应该正确呈现绝对链接,前提server.use-forward-headers
是true
在您的中设置application.properties
。
如果您的应用程序在Cloud Foundry或Heroku中运行,则该
server.use-forward-headers
属性默认为true
。在所有其他情况下,默认为false
。
自定义Tomcat的代理配置
如果使用Tomcat,还可以配置用于携带“转发”信息的标头名称,如以下示例所示:
1 | server.tomcat.remote-ip-header=x-your-remote-ip-header |
Tomcat还配置了一个默认的正则表达式,该表达式匹配要信任的内部代理。默认情况下,IP地址中10/8
,192.168/16
, 169.254/16
和127/8
是值得信赖的。您可以通过添加条目来自定义阀门的配置application.properties
,如以下示例所示:
1 | server.tomcat.internal-proxies=192\\.168\\.\\d{1,3}\\.\\d{1,3} |
仅当使用属性文件进行配置时,才需要双反斜杠。如果使用YAML,则单个反斜杠就足够了,并且值等于前面示例中显示的值
192\.168\.\d{1,3}\.\d{1,3}
。
您可以通过将其设置
internal-proxies
为空来信任所有代理(但在生产中不这样做)。
您可以RemoteIpValve
通过关闭自动关闭(为此,设置server.use-forward-headers=false
)并在TomcatServletWebServerFactory
bean中添加新的阀门实例来完全控制Tomcat的配置。
使用Tomcat启用多个连接器
可以添加org.apache.catalina.connector.Connector
到 TomcatServletWebServerFactory
,这可以允许多个连接器,包括HTTP和HTTPS连接器,显示在下面的例子:
1 |
|
使用Tomcat的LegacyCookieProcessor
默认情况下,Spring Boot使用的嵌入式Tomcat不支持Cookie格式的“Version 0”,因此您可能会看到以下错误:
1 | java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value |
如果可能的话,您应该考虑将代码更新为仅存储符合以后Cookie规范的值。但是,如果您无法更改cookie的写入方式,则可以将Tomcat配置为使用LegacyCookieProcessor
。要切换到LegacyCookieProcessor
,请使用WebServerFactoryCustomizer
添加a 的 bean TomcatContextCustomizer
,如以下示例所示:
1 |
|
使用Undertow启用多个侦听器
一个添加UndertowBuilderCustomizer
到UndertowServletWebServerFactory
与收听添加到Builder
,如图所示在下面的例子:
1 |
|
使用@ServerEndpoint创建WebSocket端点
如果要在使用@ServerEndpoint
嵌入式容器的Spring Boot应用程序中使用,则必须声明一个ServerEndpointExporter
@Bean
,如以下示例所示:
1 |
|
前面示例中显示的@ServerEndpoint
bean使用基础WebSocket容器注册任何带注释的bean。当部署到独立的servlet容器时,此角色由servlet容器初始化程序执行,并且ServerEndpointExporter
不需要该 bean。