使用的成本越低,内部封装越复杂;
一、Tomcat 集成
1、依赖层级
在 SpringBoot 框架的 web 依赖包中,引入的是内嵌 Tomcat 组件,基于 SpringBoot 的版本,Tomcat 集成的是 9.0 版本;
<!-- 1、项目工程依赖 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.2.5.RELEASE</version></dependency>
<!-- 2、starter-web依赖 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.2.5.RELEASE</version> <scope>compile</scope></dependency>
<!-- 3、starter-tomcat依赖 --><dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>9.0.31</version> <scope>compile</scope></dependency>
复制代码
2、自动化配置
在 SpringBoot 框架的自动配置类中,Web 项目中不显式更换其他服务依赖时,默认提供了对 Tomcat 服务的管理;
@ConditionalOnWebApplication(type = Type.SERVLET)@EnableConfigurationProperties(ServerProperties.class)@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, ServletWebServerFactoryConfiguration.EmbeddedTomcat.class})public class ServletWebServerFactoryAutoConfiguration {
@Bean @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat") public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer( ServerProperties serverProperties) { return new TomcatServletWebServerFactoryCustomizer(serverProperties); }}
复制代码
二、Tomcat 架构
Server:代表整个 Tomcat 容器;
Service:服务器内部的中间组件,将一个或多个 Connector 绑定到一个 Engine 上;
Engine:表示特定服务的请求处理管道,接收 Connector 的请求并响应;
Host:网络主机名称;
Connector:连接器处理与客户端的通信;
Context:代表一个 Web 应用程序的上下文;
参考 Tomcat9.0 版本的核心组件描述,对于框架有大致的了解后,再去分析集成原理,会更容易把握主线逻辑;
三、Tomcat 配置
1、基础配置
在配置文件中,对 Tomcat 做一些基础性的设置,查看下面的配置类可以知道,这些属性存在默认值;
server: port: 8082 # 端口号 tomcat: # Tomcat组件 uri-encoding: UTF-8 # URI编码 max-threads: 100 # 最大工作线程 min-spare-threads: 10 # 最小工作线程
复制代码
2、属性配置类
在服务配置中,提供多种服务器的适配,像 Tomcat、Jetty、Netty、Undertow,从策略上看,配置分为公共属性以及各种服务器的适配属性;
更多配置信息,可以参考完整的源码和注释说明;
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)public class ServerProperties { private Integer port; public static class Tomcat { private Charset uriEncoding = StandardCharsets.UTF_8; private int maxThreads = 200; private int minSpareThreads = 10; }}
复制代码
3、配置加载分析
public class TomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory> { @Override public void customize(ConfigurableTomcatWebServerFactory factory) { ServerProperties properties = this.serverProperties; ServerProperties.Tomcat tomcatProperties = properties.getTomcat(); PropertyMapper propertyMapper = PropertyMapper.get(); customizeStaticResources(factory); }}
复制代码
public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware { @Override public WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new Tomcat(); Connector connector = new Connector(this.protocol); connector.setThrowOnFailure(true); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); configureEngine(tomcat.getEngine()); prepareContext(tomcat.getHost(), initializers); return getTomcatWebServer(tomcat); }}
复制代码
四、周期管理方法
1、控制类
public interface WebServer {
// 获取监听的端口 int getPort(); // 服务启动 void start() throws WebServerException;
// 服务停止 void stop() throws WebServerException;}
复制代码
public class TomcatWebServer implements WebServer {
private final Tomcat tomcat;
private final Map<Service, Connector[]> serviceConnectors = new HashMap<>();}
复制代码
public class Tomcat {
protected Server server; protected int port = 8080; protected String hostname = "localhost"; // 初始化服务 public void init() throws LifecycleException { getServer(); server.init(); } // 启动服务 public void start() throws LifecycleException { getServer(); server.start(); }
// 停止服务 public void stop() throws LifecycleException { getServer(); server.stop(); }}
复制代码
2、核心方法
2.1 初始化,初始化时,调用 Apache-Tomcat 类中启动方法;
public class TomcatWebServer implements WebServer { /** * 初始化方法 */ private void initialize() throws WebServerException { // 控制台日志 logger.info("Tomcat initialized with port(s): " + getPortsDescription(false)); synchronized (this.monitor) { // 调用Apache-Tomcat类中启动方法 this.tomcat.start(); } }}
复制代码
2.2 启动,在初始化的方法中,调用的 Tomcat 启动方法,这里对状态进行校验并输出日志;
public class TomcatWebServer implements WebServer { /** * 启动方法 */ public void start() throws WebServerException { synchronized (this.monitor) { if (this.started) { return; } checkThatConnectorsHaveStarted(); // 启动状态的标识 this.started = true; // 控制台日志 logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '" + getContextPath() + "'"); } }}
复制代码
2.3 停止,在组件生命周期的常规管理逻辑中,停止服务之后进行销毁动作的执行,其中自然涉及到多个状态标识的转换;
public class TomcatWebServer implements WebServer { /** * 停止方法 */ public void stop() throws WebServerException { synchronized (this.monitor) { // 状态变化 boolean wasStarted = this.started; this.started = false; // Tomcat服务停止 stopTomcat(); this.tomcat.destroy(); } }}
复制代码
五、参考源码
编程文档:https://gitee.com/cicadasmile/butte-java-note
应用仓库:https://gitee.com/cicadasmile/butte-flyer-parent
复制代码
评论