1. 概述
Spring Boot 2 发布后,不少老项目在升级时都会遇到一个常见问题:编译报错找不到 EmbeddedServletContainerCustomizer
和 ConfigurableEmbeddedServletContainer
。
✅ 这两个类确实被移除了,但别慌——功能不仅没丢,还更清晰了。
❌ 直接搜“类不存在”然后瞎改,很容易踩坑。
取而代之的是:
WebServerFactoryCustomizer
接口(替代EmbeddedServletContainerCustomizer
)ConfigurableServletWebServerFactory
类(替代ConfigurableEmbeddedServletContainer
)
本文带你平滑过渡,快速完成升级。
2. Spring Boot 2 之前的写法
在 Spring Boot 1.x 中,自定义内嵌 Web 容器(如 Tomcat)的常见方式是实现 EmbeddedServletContainerCustomizer
接口。
基础配置示例
@Component
public class CustomContainer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(8080);
container.setContextPath("");
}
}
这段代码干了两件事:
- 将服务端口改为
8080
- 将上下文路径(context path)设为空,即应用根路径为
/
针对特定容器的定制(如 Tomcat)
如果需要调用 Tomcat 特有的 API,会做类型判断:
@Component
public class CustomContainer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
TomcatEmbeddedServletContainerFactory tomcatContainer =
(TomcatEmbeddedServletContainerFactory) container;
tomcatContainer.setPort(8080);
tomcatContainer.setContextPath("");
}
}
}
⚠️ 这种写法在 Spring Boot 2 中直接编译失败,因为相关类已被移除。
3. 升级到 Spring Boot 2 的正确姿势
Spring Boot 2 统一了 Web 容器的抽象模型,引入了新的命名规范:
旧类/接口(Spring Boot 1.x) | 新类/接口(Spring Boot 2+) |
---|---|
EmbeddedServletContainerCustomizer |
WebServerFactoryCustomizer |
ConfigurableEmbeddedServletContainer |
ConfigurableServletWebServerFactory |
TomcatEmbeddedServletContainerFactory |
TomcatServletWebServerFactory |
JettyEmbeddedServletContainerFactory |
JettyServletWebServerFactory |
UndertowEmbeddedServletContainerFactory |
UndertowServletWebServerFactory |
通用配置写法(推荐)
适用于所有 Servlet 容器的通用定制:
@Component
public class CustomContainer implements
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
factory.setPort(8080);
factory.setContextPath("");
}
}
✅ 简单粗暴,无需关心底层是 Tomcat 还是 Undertow,只要它是 Servlet 容器就能生效。
针对 Tomcat 的定制
若需调用 Tomcat 特有方法(比如连接器配置、线程池等),应使用具体工厂类型作为泛型:
@Component
public class CustomContainer implements
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
factory.setContextPath("");
factory.setPort(8080);
// 此处还可调用 Tomcat 专属方法,如:
// factory.addConnectorCustomizers(connector -> { ... });
}
}
📌 提示:TomcatServletWebServerFactory
提供了更多 Tomcat 特有的扩展点,比如添加连接器定制器、设置 SSL、启用 HTTP2 等。
其他容器同理:
- Jetty →
JettyServletWebServerFactory
- Undertow →
UndertowServletWebServerFactory
只要按新命名规则替换即可,API 设计保持一致。
4. 总结
Spring Boot 2 的这次重构并非功能删除,而是接口规范化的结果。
关键点回顾:
✅ 使用 WebServerFactoryCustomizer<T>
替代旧的 EmbeddedServletContainerCustomizer
✅ 泛型参数选择合适的 *ServletWebServerFactory
实现
✅ 通用需求用 ConfigurableServletWebServerFactory
,特定容器用具体工厂类
✅ 所有配置仍通过 @Component
注入 Spring 容器生效
示例代码已整理至 GitHub:https://github.com/spring-tutorials/spring-boot-web-customization
升级不难,关键是理解背后的抽象模型变化。掌握这套新机制后,后续扩展容器行为(比如自定义错误页、SSL 配置、访问日志等)也会更加得心应手。