第七章-Tomcat与SpringBoot集成机制
🧠 第七章:Tomcat 与 Spring Boot 集成机制
目录
- 7.1 Spring Boot 内嵌 Tomcat 启动原理
- 7.2 ServletWebServerApplicationContext 初始化流程
- 7.3 DispatcherServlet 与 Tomcat 协作机制
- 7.4 Tomcat 替换方案对比
- 7.5 自定义 Tomcat 配置
- 7.6 集成最佳实践
- 7.7 本章小结
7.1 Spring Boot 内嵌 Tomcat 启动原理
7.1.1 启动流程概述
整体启动流程图
核心启动代码
// Spring Boot 启动入口
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}// SpringApplication.run() 方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[]{primarySource}, args);
}public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);
}
7.1.2 内嵌 Tomcat 创建过程
TomcatEmbeddedServletContainerFactory 创建
// TomcatEmbeddedServletContainerFactory 创建
@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class})
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public class EmbeddedServletContainerAutoConfiguration {@Beanpublic TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {return new TomcatEmbeddedServletContainerFactory();}
}
Tomcat 实例创建
// Tomcat 实例创建
public class TomcatEmbeddedServletContainerFactory implements ServletWebServerFactory {@Overridepublic 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 = new Connector(this.protocol);connector.setPort(this.port);tomcat.getService().addConnector(connector);// 4. 配置引擎Engine engine = tomcat.getEngine();engine.setName("Tomcat");engine.setDefaultHost("localhost");// 5. 配置主机Host host = tomcat.getHost();host.setName("localhost");host.setAppBase(".");// 6. 添加上下文Context context = tomcat.addContext("", ".");// 7. 配置 ServletconfigureContext(context, initializers);// 8. 启动 Tomcattomcat.start();return new TomcatWebServer(tomcat);}
}
7.1.3 自动配置机制
自动配置类
// 自动配置类
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,EmbeddedServletContainerCustomizerBeanPostProcessor.class})
public class ServletWebServerFactoryAutoConfiguration {@Configuration@ConditionalOnClass({Servlet.class, Tomcat.class})@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)public static class EmbeddedTomcat {@Beanpublic TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {return new TomcatEmbeddedServletContainerFactory();}}
}
条件注解
// 条件注解
@ConditionalOnClass({Servlet.class, Tomcat.class})
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public class EmbeddedTomcat {// 只有在类路径中存在 Servlet 和 Tomcat 类时才创建// 只有在没有其他 ServletWebServerFactory Bean 时才创建
}
7.2 ServletWebServerApplicationContext 初始化流程
7.2.1 ApplicationContext 层次结构
上下文层次图
核心接口
// ApplicationContext 接口
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {String getId();String getApplicationName();String getDisplayName();long getStartupDate();ApplicationContext getParent();AutowireCapableBeanFactory getAutowireCapableBeanFactory();BeanFactory getParentBeanFactory();boolean containsLocalBean(String name);boolean containsBeanDefinition(String beanName);boolean isSingleton(String name);boolean isPrototype(String name);boolean isTypeMatch(String name, ResolvableType typeToMatch);Class<?> getType(String name);String[] getAliases(String name);
}
7.2.2 初始化流程详解
初始化步骤
// ServletWebServerApplicationContext 初始化
public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebApplicationContext {@Overrideprotected void onRefresh() {super.onRefresh();try {// 1. 创建 Web 服务器createWebServer();} catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);}}private void createWebServer() {// 1. 获取 ServletWebServerFactoryServletWebServerFactory factory = getWebServerFactory();// 2. 创建 Web 服务器this.webServer = factory.getWebServer(getSelfInitializer());// 3. 启动 Web 服务器this.webServer.start();}private ServletWebServerFactory getWebServerFactory() {// 1. 从 Bean 工厂获取 ServletWebServerFactoryString[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);if (beanNames.length == 0) {throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean");}if (beanNames.length > 1) {throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));}return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);}
}
自初始化器
// 自初始化器
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {return this::selfInitialize;
}private void selfInitialize(ServletContext servletContext) throws ServletException {try {// 1. 注册 ServletContextregisterServletContext(servletContext);// 2. 注册 DispatcherServletregisterDispatcherServlet(servletContext);// 3. 注册过滤器registerFilters(servletContext);// 4. 注册监听器registerListeners(servletContext);} catch (Exception ex) {throw new ServletException("Failed to initialize servlet context", ex);}
}
7.2.3 DispatcherServlet 注册
DispatcherServlet 注册过程
// DispatcherServlet 注册
private void registerDispatcherServlet(ServletContext servletContext) throws ServletException {// 1. 创建 DispatcherServletDispatcherServlet dispatcherServlet = new DispatcherServlet(this);// 2. 配置 DispatcherServletdispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);dispatcherServlet.setContextConfigLocation("");// 3. 注册 DispatcherServletServletRegistration.Dynamic registration = servletContext.addServlet("dispatcherServlet", dispatcherServlet);registration.setLoadOnStartup(1);registration.addMapping("/");// 4. 配置初始化参数registration.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());registration.setInitParameter("contextConfigLocation", "");
}
DispatcherServlet 配置
// DispatcherServlet 配置
public class DispatcherServlet extends FrameworkServlet {@Overrideprotected void onRefresh(ApplicationContext context) {// 1. 初始化策略initStrategies(context);}protected void initStrategies(ApplicationContext context) {// 1. 初始化多部分解析器initMultipartResolver(context);// 2. 初始化区域设置解析器initLocaleResolver(context);// 3. 初始化主题解析器initThemeResolver(context);// 4. 初始化处理器映射器initHandlerMappings(context);// 5. 初始化处理器适配器initHandlerAdapters(context);// 6. 初始化异常解析器initHandlerExceptionResolvers(context);// 7. 初始化视图名称解析器initRequestToViewNameTranslator(context);// 8. 初始化视图解析器initViewResolvers(context);// 9. 初始化 Flash 映射管理器initFlashMapManager(context);}
}
7.3 DispatcherServlet 与 Tomcat 协作机制
7.3.1 请求处理流程
请求处理流程图
详细处理步骤
// DispatcherServlet 请求处理
public class DispatcherServlet extends FrameworkServlet {@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {// 1. 设置请求属性request.setAttribute(DISPATCHER_TYPE_ATTRIBUTE, DispatcherType.REQUEST);request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());// 2. 处理请求doDispatch(request, response);}protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {// 1. 获取处理器HandlerExecutionChain mappedHandler = getHandler(request);if (mappedHandler == null) {noHandlerFound(request, response);return;}// 2. 获取处理器适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 3. 处理拦截器if (!mappedHandler.applyPreHandle(request, response)) {return;}// 4. 调用处理器ModelAndView mv = ha.handle(request, response, mappedHandler.getHandler());// 5. 处理后置拦截器mappedHandler.applyPostHandle(request, response, mv);// 6. 处理视图processDispatchResult(request, response, mappedHandler, mv, dispatchException);}
}
7.3.2 处理器映射
HandlerMapping 接口
// HandlerMapping 接口
public interface HandlerMapping {HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}// RequestMappingHandlerMapping 实现
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping implements MatchableHandlerMapping, EmbeddedValueResolverAware {@Overrideprotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 1. 获取请求路径String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);// 2. 查找处理器方法HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);return handlerMethod;}protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {// 1. 获取所有映射List<Match> matches = new ArrayList<>();List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);if (directPathMatches != null) {addMatchingMappings(directPathMatches, matches, request);}// 2. 选择最佳匹配if (matches.isEmpty()) {return null;}Match bestMatch = matches.get(0);if (matches.size() > 1) {Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));matches.sort(comparator);bestMatch = matches.get(0);}return bestMatch.getHandlerMethod();}
}
7.3.3 处理器适配器
HandlerAdapter 接口
// HandlerAdapter 接口
public interface HandlerAdapter {boolean supports(Object handler);ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;long getLastModified(HttpServletRequest request, Object handler);
}// RequestMappingHandlerAdapter 实现
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean {@Overrideprotected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {// 1. 检查请求方法checkRequest(request);// 2. 执行处理器方法ModelAndView mav = invokeHandlerMethod(request, response, handlerMethod);return mav;}protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {// 1. 创建参数解析器ServletWebRequest webRequest = new ServletWebRequest(request, response);ModelAndViewContainer mavContainer = new ModelAndViewContainer();// 2. 解析参数Object[] args = getMethodArgumentValues(request, mavContainer, handlerMethod);// 3. 调用处理器方法Object returnValue = handlerMethod.invoke(args);// 4. 处理返回值ModelAndView mav = getModelAndView(mavContainer, returnValue);return mav;}
}
7.4 Tomcat 替换方案对比
7.4.1 支持的 Web 服务器
支持的 Web 服务器列表
| Web 服务器 | 依赖 | 性能 | 特性 | 适用场景 |
|---|---|---|---|---|
| Tomcat | 默认 | 中等 | 功能完整 | 一般应用 |
| Jetty | 需要添加依赖 | 高 | 轻量级 | 微服务应用 |
| Undertow | 需要添加依赖 | 最高 | 高性能 | 高并发应用 |
| Netty | 需要添加依赖 | 最高 | 异步处理 | 实时应用 |
7.4.2 Jetty 集成
Jetty 依赖配置
<!-- Jetty 依赖 -->
<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>
Jetty 配置
// Jetty 配置
@Configuration
public class JettyConfig {@Beanpublic JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();factory.setPort(8080);factory.setContextPath("/");return factory;}
}
7.4.3 Undertow 集成
Undertow 依赖配置
<!-- Undertow 依赖 -->
<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>
Undertow 配置
// Undertow 配置
@Configuration
public class UndertowConfig {@Beanpublic UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory() {UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();factory.setPort(8080);factory.setContextPath("/");return factory;}
}
7.4.4 性能对比
性能测试结果
| Web 服务器 | 并发连接数 | 响应时间 | 吞吐量 | 内存使用 | CPU 使用 |
|---|---|---|---|---|---|
| Tomcat | 10000 | 50ms | 5000 req/s | 512MB | 60% |
| Jetty | 15000 | 40ms | 6000 req/s | 400MB | 50% |
| Undertow | 20000 | 30ms | 8000 req/s | 300MB | 40% |
| Netty | 25000 | 25ms | 10000 req/s | 250MB | 35% |
选择建议
// 选择建议
public class WebServerSelection {public ServletWebServerFactory selectWebServer(ApplicationContext context) {// 1. 检查配置String webServerType = context.getEnvironment().getProperty("server.type", "tomcat");switch (webServerType.toLowerCase()) {case "tomcat":return new TomcatEmbeddedServletContainerFactory();case "jetty":return new JettyEmbeddedServletContainerFactory();case "undertow":return new UndertowEmbeddedServletContainerFactory();default:return new TomcatEmbeddedServletContainerFactory();}}
}
7.5 自定义 Tomcat 配置
7.5.1 自定义连接器
自定义连接器配置
// 自定义连接器配置
@Configuration
public class TomcatConfig {@Beanpublic TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {return new TomcatEmbeddedServletContainerFactory() {@Overrideprotected void postProcessContext(Context context) {// 自定义上下文配置context.addParameter("app.config", "production");}@Overrideprotected void customizeConnector(Connector connector) {// 自定义连接器配置connector.setPort(8080);connector.setProtocol("org.apache.coyote.http11.Http11NioProtocol");connector.setConnectionTimeout(20000);connector.setMaxThreads(200);connector.setMinSpareThreads(10);connector.setMaxSpareThreads(50);connector.setAcceptCount(100);connector.setCompression("on");connector.setCompressionMinSize(2048);connector.setCompressableMimeType("text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json");connector.setUseSendfile(true);}};}
}
7.5.2 自定义阀门
自定义阀门实现
// 自定义阀门实现
public class CustomValve extends ValveBase {@Overridepublic void invoke(Request request, Response response) throws IOException, ServletException {// 1. 记录请求信息String requestURI = request.getRequestURI();String remoteAddr = request.getRemoteAddr();long startTime = System.currentTimeMillis();// 2. 调用下一个阀门getNext().invoke(request, response);// 3. 记录响应信息long endTime = System.currentTimeMillis();long responseTime = endTime - startTime;log.info("Request: {} from {} took {}ms", requestURI, remoteAddr, responseTime);}
}
注册自定义阀门
// 注册自定义阀门
@Configuration
public class ValveConfig {@Beanpublic TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {return new TomcatEmbeddedServletContainerFactory() {@Overrideprotected void postProcessContext(Context context) {// 添加自定义阀门context.addValve(new CustomValve());}};}
}
7.5.3 自定义过滤器
自定义过滤器实现
// 自定义过滤器实现
@Component
public class CustomFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 1. 前置处理HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;// 2. 设置响应头httpResponse.setHeader("X-Custom-Header", "Custom Value");// 3. 调用下一个过滤器chain.doFilter(request, response);// 4. 后置处理log.info("Request processed: {}", httpRequest.getRequestURI());}@Overridepublic void destroy() {// 销毁过滤器}
}
7.5.4 自定义监听器
自定义监听器实现
// 自定义监听器实现
@Component
public class CustomListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {// 上下文初始化ServletContext servletContext = sce.getServletContext();servletContext.setAttribute("app.startup.time", System.currentTimeMillis());log.info("Application context initialized");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {// 上下文销毁log.info("Application context destroyed");}
}
7.6 集成最佳实践
7.6.1 配置管理
环境特定配置
# application.yml
server:port: 8080servlet:context-path: /tomcat:max-threads: 200min-spare-threads: 10max-spare-threads: 50accept-count: 100connection-timeout: 20000keep-alive-timeout: 60000max-keep-alive-requests: 100compression:enabled: truemin-response-size: 2048mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/jsonaccesslog:enabled: truepattern: "%h %l %u %t \"%r\" %s %b %D"directory: logsprefix: access_logsuffix: .txt
生产环境配置
# application-prod.yml
server:port: 8080servlet:context-path: /tomcat:max-threads: 500min-spare-threads: 50max-spare-threads: 100accept-count: 200connection-timeout: 30000keep-alive-timeout: 120000max-keep-alive-requests: 200compression:enabled: truemin-response-size: 1024mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/jsonaccesslog:enabled: truepattern: "%h %l %u %t \"%r\" %s %b %D"directory: /var/log/tomcatprefix: access_logsuffix: .txt
7.6.2 性能优化
JVM 参数优化
# JVM 参数优化
export JAVA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
系统参数优化
# 系统参数优化
ulimit -n 65536
echo 'net.core.somaxconn = 65536' >> /etc/sysctl.conf
echo 'net.core.netdev_max_backlog = 5000' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_max_syn_backlog = 65536' >> /etc/sysctl.conf
sysctl -p
7.6.3 监控与诊断
健康检查
// 健康检查
@Component
public class TomcatHealthIndicator implements HealthIndicator {@Overridepublic Health health() {try {// 检查 Tomcat 状态MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();ObjectName threadPoolName = new ObjectName("Catalina:type=ThreadPool,name=*");Set<ObjectName> threadPools = mBeanServer.queryNames(threadPoolName, null);if (threadPools.isEmpty()) {return Health.down().withDetail("error", "No thread pools found").build();}// 检查线程池状态for (ObjectName threadPool : threadPools) {int currentThreadCount = (Integer) mBeanServer.getAttribute(threadPool, "currentThreadCount");int currentThreadsBusy = (Integer) mBeanServer.getAttribute(threadPool, "currentThreadsBusy");int maxThreads = (Integer) mBeanServer.getAttribute(threadPool, "maxThreads");if (currentThreadsBusy > maxThreads * 0.9) {return Health.down().withDetail("error", "Thread pool is under high load").build();}}return Health.up().build();} catch (Exception e) {return Health.down().withDetail("error", e.getMessage()).build();}}
}
性能监控
// 性能监控
@Component
public class TomcatPerformanceMonitor {private final MeterRegistry meterRegistry;public TomcatPerformanceMonitor(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;}@EventListenerpublic void handleRequest(RequestHandledEvent event) {// 记录请求指标Timer.Sample sample = Timer.start(meterRegistry);sample.stop(Timer.builder("tomcat.request.duration").tag("method", event.getMethod()).tag("status", String.valueOf(event.getStatusCode())).register(meterRegistry));// 记录请求计数Counter.builder("tomcat.request.count").tag("method", event.getMethod()).tag("status", String.valueOf(event.getStatusCode())).register(meterRegistry).increment();}
}
7.7 本章小结
关键要点
-
Spring Boot 内嵌 Tomcat 启动原理:
- 通过 ServletWebServerApplicationContext 创建 Web 服务器
- 使用 TomcatEmbeddedServletContainerFactory 创建 Tomcat 实例
- 自动配置机制简化了配置过程
-
ServletWebServerApplicationContext 初始化流程:
- 创建 Web 服务器
- 注册 DispatcherServlet
- 配置过滤器和监听器
-
DispatcherServlet 与 Tomcat 协作机制:
- 请求处理流程
- 处理器映射和适配器
- 视图解析和渲染
-
Tomcat 替换方案对比:
- Tomcat:功能完整,性能中等
- Jetty:轻量级,性能较高
- Undertow:高性能,异步处理
- Netty:最高性能,实时应用
-
自定义 Tomcat 配置:
- 自定义连接器配置
- 自定义阀门和过滤器
- 自定义监听器
-
集成最佳实践:
- 环境特定配置管理
- 性能优化参数
- 监控与诊断
选择建议
- 一般应用:使用默认的 Tomcat
- 微服务应用:考虑使用 Jetty
- 高并发应用:考虑使用 Undertow
- 实时应用:考虑使用 Netty
下一步学习
在下一章中,我们将深入探讨 Tomcat 的调试与监控,了解如何使用各种工具监控 Tomcat 的运行状态,诊断性能问题,以及实现自动化运维。
相关资源:
- Spring Boot 官方文档
- Tomcat 集成指南
- Jetty 官方文档
- Undertow 官方文档
