深入探索 Spring Boot3 中自定义 Tomcat 配置的奥秘

在当今的互联网软件开发领域,Spring Boot 已然成为众多项目的首选框架。当我们引入 spring-boot-starter-web 等相关 starter 后,应用程序便能自动启动 Tomcat Web 服务器并开始接收 HTTP 请求,这都得益于 Spring Boot 强大的自动配置机制。但在实际开发中,我们常常会遇到默认配置无法满足业务需求的情况,此时就需要进行自定义 Tomcat 配置。今天,就带大家深入探索 Spring Boot3 中自定义 Tomcat 配置的奥秘,让你的开发工作更加得心应手。

Spring Boot 自动配置机制的核心概念

在深入探讨自定义 Tomcat 配置之前,我们先来了解一下 Spring Boot 自动配置机制中的两个核心概念:@AutoConfiguration(自动配置类)和 @Conditional 注解(条件匹配) 。

(一)@AutoConfiguration

对于使用过 Spring 框架的开发者来说,@Configuration 注解并不陌生,我们常用它来进行自定义的 Bean 配置。而 @AutoConfiguration 则是专门用于自动配置类的注解,这些加了 @AutoConfiguration 注解的自动配置类便是自动配置的入口。它本身也使用了 @Configuration 注解,这表明自动配置类也是一个标准的配置类。与标准配置类相同,自动配置类的核心内容也是配置 Bean,不过它会在此基础上添加各种条件和规则,只有满足特定条件和规则,这些 Bean 才会生效。并且,这些条件规则还能应用到自动配置类本身,控制整个自动配置类的开启与否。通常,一个特定的自包含特性功能会对应一个自动配置类,但配置不一定都要写在这一个类里,可以分解为多个普通的 @Configuration 配置类,然后通过 @Import 引入。

以 Servlet Web 服务器相关功能的自动配置为例,其入口是自动配置类
ServletWebServerFactoryAutoConfiguration 。这个自动配置类上有诸多注解,例如:

  • @AutoConfiguration (after = SslAutoConfiguration.class) :告诉 Spring 框架这个类是用于自动配置的,并且有些自动配置的初始化有先后依赖关系,这里通过 after 声明了依赖关系。
  • @AutoConfigureOrder (Ordered.HIGHEST_PRECEDENCE) :设置自动配置类加载的顺序。
  • @ConditionalOnClass 和 @ConditionalOnWebApplication :这两个注解就是自动配置生效的条件和规则,只有当满足相应条件时,该自动配置类才会生效。
  • @EnableConfigurationProperties (ServerProperties.class) :自动配置提供的自定义参数,比如 server.port 等就可以在这里进行配置。
  • @Import ({...}) :复杂的配置建议按功能或范围拆分成子配置,然后通过 @Import 引入。要注意,引入的顺序会影响条件的匹配,尤其是选项类的配置(比如选择 Tomcat,Jetty 还是 Undertow)。

(二)查找自动配置类

那么,Spring Boot 是如何知道要加载某个自动配置类的呢?原来,Spring 定义了一套自动配置专用的发现机制,即通过 jar 包里的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。该文件的每一行就是一个自动配置类的完全限定名,像 spring-boot-autoconfigure 包里该文件中就包含
ServletWebServerFactoryAutoConfiguration 。具体的加载逻辑可以查看源码
AutoConfigurationImportSelector#
getCandidateConfigurations 。值得一提的是,imports 文件是 Spring 2.7 新引入的发现机制,之前版本使用的是另一种方式。

了解了自动配置机制的核心概念后,我们进入今天的重点 —— 如何在 Spring Boot3 中进行自定义 Tomcat 配置。

通过 application.properties 文件进行自定义 Tomcat 配置

在 Spring Boot 项目中,我们可以在 application.properties 文件中进行许多 Tomcat 相关的自定义配置。下面为大家详细介绍一些常见的配置项。

服务器地址和端口

端口号是我们最常更改的配置之一。默认情况下,Tomcat 的端口为 8080,如果我们想修改,可以在 application.properties 文件中添加如下配置:

server.port = 8081

若我们不提供 server.port 参数,Tomcat 就会使用默认的 8080 端口。在某些场景下,我们可能还希望设置服务器应绑定的网络地址,即定义服务器将监听的 IP 地址,例如:

server.address = 127.0.0.1

默认情况下,该值设置为 0.0.0.0,允许通过所有 IPv4 地址进行连接。而设置为 127.0.0.1(localhost),则会使服务器更具选择性,只有本地的请求能访问。

错误处理

默认情况下,Spring Boot 提供标准错误网页,也就是 Whitelabel 。它默认是启用的,但如果我们不想显示任何错误信息,可以将其禁用,配置如下:

server.error.whitelabel.enabled = false

Whitelabel 的默认路径是 /error,我们也可以通过设置 server.error.path 参数来自定义它,比如:

server.error.path = /customError

此外,我们还能设置属性,以确定显示有关错误的信息,比如是否包含错误消息和堆栈跟踪等。

服务器连接

在低资源容器上运行时,我们可能希望减少 CPU 和内存负载,其中一种方法就是限制应用程序可以同时处理的请求数量。相反,如果服务器资源充足,我们也可以增加此值以获得更好的性能。在 Spring Boot 中,我们可以通过以下配置定义 Tomcat 工作线程的最大数量:

server.tomcat.max-threads = 500

这里将最大线程数设置为了 500,默认值为 200。除了最大线程数,我们还可以设置服务器连接超时时间,这表示服务器在连接关闭之前等待客户端发出请求的最长时间,配置如下:

server.connection-timeout = 5s

这里设置的超时时间为 5 秒。另外,我们还能定义请求头的最大大小、请求正文的最大大小以及整个 POST 请求的最大大小,相关配置如下:

server.max-http-header-size = 8KB
server.tomcat.max-swallow-size = 2MB
server.tomcat.max-http-post-size = 2MB

SSL

若要在 Spring Boot 应用程序中启用 SSL 支持,我们需要进行一系列配置。首先,将 server.ssl.enabled 属性设置为 true,并定义 SSL 协议:

server.ssl.enabled = true
server.ssl.protocol = TLS

然后,我们要配置保存证书密钥库的密码、类型和路径,以及标识密钥库中密钥的别名,示例如下:

server.ssl.key-store-password = my_password
server.ssl.key-store-type = keystore_type
server.ssl.key-store = keystore-path
server.ssl.key-alias = tomcat

访问日志

在统计页面命中数、用户会话活动等场景中,Tomcat 访问日志非常有用。要启用访问日志,我们只需在 application.properties 文件中进行如下设置:

server.tomcat.accesslog.enabled = true

同时,我们还应该配置其他参数,例如附加到日志文件的目录名、前缀、后缀和日期格式等,配置示例如下:

server.tomcat.accesslog.directory = logs
server.tomcat.accesslog.prefix = access_log
server.tomcat.accesslog.suffix = .log
server.tomcat.accesslog.file-date-format = yyyy-MM-dd

通过编程方式进行自定义 Tomcat 配置

除了在 application.properties 文件中进行配置,我们还可以通过编程的方式来实现自定义 Tomcat 配置。在 Spring Boot 的文档中有相关配置 Tomcat 的示例,如下:

public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.setPort(9000);
    factory.setSessionTimeout(10, TimeUnit.MINUTES);
    return factory;
}

上述示例展示了比较简单的配置,其他配置参数可以在 factory 类中查找。例如,要配置 Connector 相关的参数,可以通过 addConnectorCustomizers () 添加指定方法。若想了解如何实现 TomcatConnectorCustomizer ,可参考实现类 SslConnectorCustomizer 。

从 Spring 自动配置的角度来看,在 spirng.factories 中包含
EmbeddedWebServerFactoryCustomizerAutoConfiguration 和
ServletWebServerFactoryAutoConfiguration 这两个自动配置类。
ServletWebServerFactoryAutoConfiguration 会初始化
ServletWebServerFactoryCustomizer(配置通用的 servlet 信息,包含端口、上下文路径、应用名、Session 配置、Servlet 携带的初始变量等等)和
TomcatServletWebServerFactoryCustomizer(配置 tomcat 的额外信息,如 redirectContextRoot (是否在请求根上下文时转发,true 则转发路径为 /demoWeb/) 和 useRelativeRedirects (是否使用相对路径) 等路径跳转问题处理)这两个定制类。

除此之外,
ServletWebServerFactoryAutoConfiguration 还引入了
BeanPostProcessorsRegistrar ,这个类是用来注册
WebServerFactoryCustomizerBeanPostProcessor ,它的作用是在完成 bean 的 Initialization 之前将
WebServerFactoryCustomizer 的自定义配置应用到 WebServerFactory 上。
EmbeddedWebServerFactoryCustomizerAutoConfiguration 会根据配置文件决定注入 Tomcat 、Jetty 或者 Undertow 的定制类。

将定制的配置应用到 Web 容器上的任务是由
ServletWebServerApplicationContext 以及
WebServerFactoryCustomizerBeanPostProcessor 完成的。

总结

通过本文的介绍,相信大家对 Spring Boot3 中自定义 Tomcat 配置有了全面而深入的了解。无论是通过 application.properties 文件进行常规配置,还是通过编程方式实现更灵活的定制,都能帮助我们更好地满足项目的实际需求。在实际开发过程中,大家可以根据具体情况选择合适的配置方式,充分发挥 Spring Boot 和 Tomcat 的强大功能。希望本文能为各位互联网软件开发人员在 Spring Boot 开发中提供有力的帮助,让我们在开发之路上更加顺畅。各位开发者们,不妨赶紧动手实践一下,将这些自定义配置运用到你的项目中吧!

原文链接:,转发请注明来源!