全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

内嵌 Web 容器启动

内嵌 Web 容器是 Spring Boot 的核心特性,将容器启动与 Spring 生命周期集成。

容器启动时机

refresh() 流程中的容器启动

Java
public void refresh() throws BeansException {
    // ...
    // onRefresh() 创建 Web 容器
    onRefresh();

    // finishRefresh() 启动 Web 容器
    finishRefresh();
}

ServletWebServerApplicationContext.onRefresh()

Java
protected void onRefresh() {
    super.onRefresh();
    try {
        createWebServer();
    } catch (Throwable ex) {
        throw new ApplicationContextException("Unable to start web server", ex);
    }
}

private void createWebServer() {
    WebServer webServer = null;
    ServletWebServerFactory factory = getWebServerFactory();

    // 创建容器(不启动)
    webServer = factory.getWebServer(getSelfInitializer());

    this.webServer = webServer;
    initPropertySources();
}

ServletWebServerFactory

工厂接口

Java
public interface ServletWebServerFactory {
    WebServer getWebServer(ServletContextInitializer... initializers);
}

Tomcat 工厂实现

Java
public class TomcatServletWebServerFactory implements ServletWebServerFactory {
    @Override
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        // 1. 创建 Tomcat 实例
        Tomcat tomcat = new Tomcat();

        // 2. 设置基础目录
        File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());

        // 3. 创建 Connector
        Connector connector = new Connector(this.protocol);
        connector.setPort(this.port);
        tomcat.getService().addConnector(connector);

        // 4. 配置 Host
        Host host = tomcat.getHost();
        host.setAutoDeploy(false);

        // 5. 创建 Context
        Context context = tomcat.addContext("", baseDir.getAbsolutePath());

        // 6. 配置 ServletContextInitializer
        configureContext(context, initializers);

        // 7. 返回 TomcatWebServer
        return new TomcatWebServer(tomcat, this.port);
    }
}

WebServer 实现

TomcatWebServer

Java
public class TomcatWebServer implements WebServer {
    private final Tomcat tomcat;
    private final int port;

    @Override
    public void start() throws WebServerException {
        // 启动 Tomcat
        this.tomcat.start();

        // 等待容器就绪
        awaitContainerStarted();

        // 发布启动事件
        publishStartedEvent();
    }

    @Override
    public void stop() throws WebServerException {
        // 停止 Tomcat
        this.tomcat.stop();
    }

    @Override
    public int getPort() {
        return this.port;
    }
}

UndertowWebServer

Java
public class UndertowWebServer implements WebServer {
    private final Undertow.Builder builder;

    @Override
    public void start() throws WebServerException {
        // 构建 Undertow 实例
        Undertow undertow = this.builder.build();

        // 启动
        undertow.start();

        this.undertow = undertow;
    }
}

finishRefresh() 启动容器

容器启动触发

Java
protected void finishRefresh() {
    super.finishRefresh();

    // 启动 WebServer
    WebServer webServer = startWebServer();
    if (webServer != null) {
        publishEvent(new WebServerInitializedEvent(webServer));
    }
}

private WebServer startWebServer() {
    WebServer webServer = this.webServer;
    if (webServer != null) {
        webServer.start();
    }
    return webServer;
}

ServletContextInitializer

初始化器接口

Java
public interface ServletContextInitializer {
    void onStartup(ServletContext servletContext) throws ServletException;
}

SelfInitializer 实现

Java
private ServletContextInitializer getSelfInitializer() {
    return this::selfInitialize;
}

private void selfInitialize(ServletContext servletContext) throws ServletException {
    // 准备 ServletContext
    prepareWebApplicationContext(servletContext);

    // 注册 Servlet、Filter、Listener
    registerServlets(servletContext);
    registerFilters(servletContext);
    registerListeners(servletContext);
}

注册 DispatcherServlet

Java
@Bean
public DispatcherServlet dispatcherServlet() {
    return new DispatcherServlet();
}

@Bean
public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration() {
    ServletRegistrationBean<DispatcherServlet> registration = new ServletRegistrationBean<>();
    registration.setServlet(dispatcherServlet());
    registration.addUrlMappings("/");
    registration.setName("dispatcherServlet");
    return registration;
}

容器自动配置

ServletWebServerFactoryAutoConfiguration

Java
@AutoConfiguration
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
public class ServletWebServerFactoryAutoConfiguration {

    @Bean
    @ConditionalOnClass(Tomcat.class)
    public ServletWebServerFactory tomcatServletWebServerFactory() {
        return new TomcatServletWebServerFactory();
    }

    @Bean
    @ConditionalOnClass(Jetty.class)
    @ConditionalOnMissingBean(ServletWebServerFactory.class)
    public ServletWebServerFactory jettyServletWebServerFactory() {
        return new JettyServletWebServerFactory();
    }

    @Bean
    @ConditionalOnClass(Undertow.class)
    @ConditionalOnMissingBean(ServletWebServerFactory.class)
    public ServletWebServerFactory undertowServletWebServerFactory() {
        return new UndertowServletWebServerFactory();
    }
}

启动事件

WebServerInitializedEvent

Java
public abstract class WebServerInitializedEvent extends ApplicationEvent {
    private final WebServer webServer;

    public WebServer getWebServer() {
        return this.webServer;
    }

    public int getPort() {
        return this.webServer.getPort();
    }
}

// 具体实现
public class ServletWebServerInitializedEvent extends WebServerInitializedEvent {}

监听容器启动

Java
@Component
public class WebServerListener implements ApplicationListener<ServletWebServerInitializedEvent> {
    @Override
    public void onApplicationEvent(ServletWebServerInitializedEvent event) {
        int port = event.getPort();
        WebServer server = event.getWebServer();
        System.out.println("Web容器启动完成,端口:" + port);
    }
}

注意:容器在 finishRefresh() 阶段启动,此时所有 Bean 已完成初始化。

要点总结

  • 容器创建在 onRefresh(),启动在 finishRefresh()
  • ServletWebServerFactory 负责创建 WebServer 实例
  • ServletContextInitializer 配置 Servlet/Filter
  • 支持 Tomcat、Jetty、Undertow 三种容器
  • WebServerInitializedEvent 通知容器启动完成

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring Boot 启动流程
下一篇 → 环境准备与属性源加载
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库