当前位置: 首页 > news >正文

廊坊seo建站手机版网站建设合同

廊坊seo建站,手机版网站建设合同,静态网页制作技术,学校网站页面设计在前面我们介绍了如何通过源码来启动Tomcat#xff0c;本文我们就来看一下Tomcat是如何一步步启动的#xff0c;以及在启动过程中#xff0c;不同的组件是如何加载的。 一般#xff0c;我们可以通过 Tomcat 的 /bin 目录下的脚本 startup.sh 来启动 Tomcat#xff0c;如果…在前面我们介绍了如何通过源码来启动Tomcat本文我们就来看一下Tomcat是如何一步步启动的以及在启动过程中不同的组件是如何加载的。 一般我们可以通过 Tomcat 的 /bin 目录下的脚本 startup.sh 来启动 Tomcat如果是window那就用startup.bat来启动。 那我们执行了这个脚本后发生了什么呢 目录 1.整体结构 2.文件解析与组件创建器—Catalina 3.Catalina如何孕育出众多组件的 4.Server 组件 5.Service 组件 6.Engine 组件 1.整体结构 在一篇中我们看到tomcat启动是从类Bootstrap里的Main方法开始的因此对于Tomcat而说Bootstrap就是创造万物的工具。 之后的工作可以通过下面这张流程图来了解一下。 Tomcat 本质上是一个 Java 程序因此 startup.sh 脚本最 核心的工作就是启动一个 JVM 来运行 Tomcat 的启动类 Bootstrap。Bootstrap 的主要任务是初始化 Tomcat 的类加载器并且创建 Catalina。Catalina 是一个启动类它通过解析 server.xml来创建相应的组件并调用 Server 的 start 方法。Server 组件的职责就是管理 Service 组件它会负责调用 Service 的 start() 方法。Service 组件的职责就是管理连接器和顶层容器 Engine因此它会调用连接器和 Engine 的 start 方法。 这样 Tomcat 的启动就算完成了。下面我来详细介绍一下上面这个启动过程中提到的几个非常关键的启动类和组件。 如果我们以一个互联网大厂 比如腾宝那么 Bootstrap就是创始人马老师而Server则是不同的事业群例如支付宝、天猫、阿里云等等。Service 是事业群总经理一般事业群里会有多个部门而在Tomcat里Service管理两个职能部门一个是对外的市场部也就是连接器组件另一个是对内的研发部也就是容器组件。 再向下Engine 则是研发部经理之后的Service就是具体干活的你和我在Tomcat里就是Servlet。 2.文件解析与组件创建器—Catalina Catalina 的主要任务就是创建 Server它不是直接 new 一个 Server 实例就完事了而是需要解析 server.xml所以打开Catalina类的代码我们会发现很多篇幅都是和解析xml或者Digester类有关系后者也是解析文件的。 Catalina的作用就是把在 server.xml 里配置的各种组件一一创建出来接着调用 Server 组件的 init 方法和 start 方法这样整个 Tomcat 就启动起来了。作为“管理者”Catalina 还需要处理各种“异常”情况比如当我们通过“Ctrl C”关闭 Tomcat 时Tomcat 将如何优雅的停止并且清理资源呢因此 Catalina 在 JVM 中注册一个“关闭钩子”。 public void start() {//1. 如果持有的 Server 实例为空就解析 server.xml 创建出来if (getServer() null) {load();}//2. 如果创建失败报错退出if (getServer() null) {log.fatal(sm.getString(catalina.noServer));return;}//3. 启动 Servertry {getServer().start();} catch (LifecycleException e) {return;}// 创建并注册关闭钩子if (useShutdownHook) {if (shutdownHook null) {shutdownHook new CatalinaShutdownHook();}Runtime.getRuntime().addShutdownHook(shutdownHook);}// 用 await 方法监听停止请求if (await) {await();stop();} } 那什么是“关闭钩子”它又是做什么的呢如果我们需要在 JVM 关闭时做一些清理工作比如将缓存数据刷到磁盘上或者清理一些临时文件可以向 JVM 注册一个“关闭钩子”。“关闭钩子”其实就是一个线程JVM 在停止之前会尝试执行这个线程的 run 方法。下面我们来看看 Tomcat 的“关闭钩子”CatalinaShutdownHook 做了些什么。 protected class CatalinaShutdownHook extends Thread {Overridepublic void run() {try {if (getServer() ! null) {Catalina.this.stop();}} catch (Throwable ex) {...}} } 从这段代码中你可以看到Tomcat 的“关闭钩子”实际上就执行了 Server 的 stop 方法Server 的 stop 方法会释放和清理所有的资源。 3.Catalina如何孕育出众多组件的 我们提的这些重要的组件是在Catalina的哪里创建的呢如果没有找到位置我们总是会感觉少了点什么。 这个创建的入口是Catalina里调用createStartDigester()来创建的创建之后的内容通过Digester来管理。我们分别看创建各个组件的起始位置 【1】创建Server实例 digester.addObjectCreate(Server,org.apache.catalina.core.StandardServer,className);digester.addSetProperties(Server);digester.addSetNext(Server,setServer,org.apache.catalina.Server); Catania中Server的默认实现类是类org.apache.catalina.core.StandardServer。但是我们可以童工属性className来修改。 【2】创建全局J2EE的企业命名上下文JNDI digester.addObjectCreate(Server/GlobalNamingResources,org.apache.catalina.deploy.NamingResourcesImpl);digester.addSetProperties(Server/GlobalNamingResources);digester.addSetNext(Server/GlobalNamingResources,setGlobalNamingResources,org.apache.catalina.deploy.NamingResourcesImpl); JDNI这个名字经常见到但是从来没用过不管了。 【3】为Server增加生命周期监听器 digester.addRule(Server/Listener,new ListenerCreateRule(null, className));digester.addSetProperties(Server/Listener);digester.addSetNext(Server/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener); Server元素支持配置生命周期监听器用于为当前的Servlet实例添加LifecycleListener监听器 顺着这个方法向下看我们会可以看到为Service添加Connector等等很多组件。 看这个有什么用呢主要是帮助我们找到了学习的入口知道怎么初始化我们就能慢慢理清楚怎么工作了。 4.Server 组件 Server 组件的具体实现类是 StandardServer我们来看下 StandardServer 具体实现了哪些功能。Server 继承了 LifeCycleBase它的生命周期被统一管理并且它的子组件是 Service因此它还需要管理 Service 的生命周期也就是说在启动时调用 Service 组件的启动方法在停止时调用它们的停止方法。Server 在内部维护了若干 Service 组件它是以数组来保存的那 Server 是如何添加一个 Service 到数组中的呢 Override public void addService(Service service) {service.setServer(this);synchronized (servicesLock) {// 创建一个长度 1 的新数组Service results[] new Service[services.length 1];// 将老的数据复制过去System.arraycopy(services, 0, results, 0, services.length);results[services.length] service;services results;// 启动 Service 组件if (getState().isAvailable()) {try {service.start();} catch (LifecycleException e) {// Ignore}}// 触发监听事件support.firePropertyChange(service, null, service);}} 从上面的代码你能看到它并没有一开始就分配一个很长的数组而是在添加的过程中动态地扩展数组长度当添加一个新的 Service 实例时会创建一个新数组并把原来数组内容复制到新数组这样做的目的其实是为了节省内存空间。 这种用法很明显效率是不高的因此在工程里极少看到这里也算增长了我们的见识吧。 除此之外Server 组件还有一个重要的任务是启动一个 Socket 来监听停止端口这就是为什么你能通过 shutdown 命令来关闭 Tomcat。不知道你留意到没有上面 Caralina 的启动方法的最后一行代码就是调用了 Server 的 await 方法。 在 await 方法里会创建一个 Socket 监听 8005 端口并在一个死循环里接收 Socket 上的连接请求如果有新的连接到来就建立连接然后从 Socket 中读取数据如果读到的数据是停止命令“SHUTDOWN”就退出循环进入 stop 流程。 5.Service 组件 Service 组件的具体实现类是 StandardService我们先来看看它的定义以及关键的成员变量。 public class StandardService extends LifecycleBase implements Service {// 名字private String name null;//Server 实例private Server server null;// 连接器数组protected Connector connectors[] new Connector[0];private final Object connectorsLock new Object();// 对应的 Engine 容器private Engine engine null;// 映射器及其监听器protected final Mapper mapper new Mapper();protected final MapperListener mapperListener new MapperListener(this); StandardService 继承了 LifecycleBase 抽象类此外 StandardService 中还有一些我们熟悉的组件比如 Server、Connector、Engine 和 Mapper。 那为什么还有一个 MapperListener这是因为 Tomcat 支持热部署当 Web 应用的部署发生变化时Mapper 中的映射信息也要跟着变化MapperListener 就是一个监听器它监听容器的变化并把信息更新到 Mapper 中这是典型的观察者模式。 作为“管理”角色的组件最重要的是维护其他组件的生命周期。此外在启动各种组件时要注意它们的依赖关系也就是说要注意启动的顺序。我们来看看 Service 启动方法 protected void startInternal() throws LifecycleException {//1. 触发启动监听器setState(LifecycleState.STARTING);//2. 先启动 EngineEngine 会启动它子容器if (engine ! null) {synchronized (engine) {engine.start();}}//3. 再启动 Mapper 监听器mapperListener.start();//4. 最后启动连接器连接器会启动它子组件比如 Endpointsynchronized (connectorsLock) {for (Connector connector: connectors) {if (connector.getState() ! LifecycleState.FAILED) {connector.start();}}} } 从启动方法可以看到Service 先启动了 Engine 组件再启动 Mapper 监听器最后才是启动连接器。这很好理解因为内层组件启动好了才能对外提供服务才能启动外层的连接器组件。而 Mapper 也依赖容器组件容器组件启动好了才能监听它们的变化因此 Mapper 和 MapperListener 在容器组件之后启动。组件停止的顺序跟启动顺序正好相反的也是基于它们的依赖关系。 6.Engine 组件 最后我们再来看看顶层的容器组件 Engine 具体是如何实现的。Engine 本质是一个容器因此它继承了 ContainerBase 基类并且实现了 Engine 接口。 public class StandardEngine extends ContainerBase implements Engine { } 我们知道Engine 的子容器是 Host所以它持有了一个 Host 容器的数组这些功能都被抽象到了 ContainerBase 中ContainerBase 中有这样一个数据结构 protected final HashMapString, Container children new HashMap();ContainerBase 用 HashMap 保存了它的子容器并且 ContainerBase 还实现了子容器的“增删改查”甚至连子组件的启动和停止都提供了默认实现比如 ContainerBase 会用专门的线程池来启动子容器。 for (int i 0; i children.length; i) {results.add(startStopExecutor.submit(new StartChild(children[i]))); } 所以 Engine 在启动 Host 子容器时就直接重用了这个方法。 那 Engine 自己做了什么呢我们知道容器组件最重要的功能是处理请求而 Engine 容器对请求的“处理”其实就是把请求转发给某一个 Host 子容器来处理具体是通过 Valve 来实现的。 通过前面的学习我们知道每一个容器组件都有一个 Pipeline而 Pipeline 中有一个基础阀Basic Valve而 Engine 容器的基础阀定义如下 final class StandardEngineValve extends ValveBase {public final void invoke(Request request, Response response)throws IOException, ServletException {// 拿到请求中的 Host 容器Host host request.getHost();if (host null) {return;}// 调用 Host 容器中的 Pipeline 中的第一个 Valvehost.getPipeline().getFirst().invoke(request, response);}} 这个基础阀实现非常简单就是把请求转发到 Host 容器。你可能好奇从代码中可以看到处理请求的 Host 容器对象是从请求中拿到的请求对象中怎么会有 Host 容器呢这是因为请求到达 Engine 容器中之前Mapper 组件已经对请求进行了路由处理Mapper 组件通过请求的 URL 定位了相应的容器并且把容器对象保存到了请求对象中。
http://www.hkea.cn/news/14491219/

相关文章:

  • 长春网易网站建设网站参数设定
  • 数字营销技术应用网站深圳网站建设制作优化
  • 服装高端网站建设vue 做pc网站
  • 排名优化seo公司长沙百度推广排名优化
  • 售房网站模板做铝材哪些网站招聘
  • 白云区建材网站建设海口关键词优化报价
  • 网站设计与开发专家html网站建设方案
  • 丰金网络 做网站WordPress网站图片预加载
  • qq上网站做我女朋友网站建设网络营销平台 云搜系统
  • 企业网站建设工作流程网站怎么更改关键词
  • 网络营销从网站建设开始开一个网站要花多少钱
  • 肇庆cms建站系统网站模板种类
  • 费县网站建设足球外围网站怎么做
  • 微博网站开发平台淘宝网站的推广方案
  • 吉林建设教育协会网站seo教程书籍
  • 魏县网站建设推广wordpress寻模板
  • 武威建设银行网站网络推广外包内容
  • 网站开发费用如何记账铁岭做网站信息
  • 临沂网站改版电商类网站咋做
  • 个人博客网站开发的意义网站关键词优化多少钱
  • 可以做旅行计划的网站网站内容全屏截屏怎么做
  • 网站推广服务好公司排名网站收录做关键词排名
  • 赣州建站九江市seo
  • 建网站做淘宝客可以吗网站虚拟主机
  • 网站建设方面的销售经验一起做网店17广州沙河
  • 搜索引擎网站排名优化方案大连建设工业产品网站
  • 建设企业网站开发公司未成年人思想道德建设网站
  • 百度云自助建站wordpress会被黑吗
  • 自己做卖东西的网站庆阳市建设局网站
  • 做小程序的平台seo关键词优化方案