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

昌吉做网站推广的公司广告牌设计模板

昌吉做网站推广的公司,广告牌设计模板,哪个网站是专门做男人衣服的,速卖通官网深入拆解TomcatJetty#xff08;三#xff09; 专栏地址#xff1a;https://time.geekbang.org/column/intro/100027701 1 Tomcat组件生命周期 Tomcat如何如何实现一键式启停 Tomcat 架构图和请求处理流程如图所示#xff1a; 对组件之间的关系进行分析#xff0c;…深入拆解TomcatJetty三 专栏地址https://time.geekbang.org/column/intro/100027701 1 Tomcat组件生命周期 Tomcat如何如何实现一键式启停 Tomcat 架构图和请求处理流程如图所示 对组件之间的关系进行分析发现启动时需要遵循以下两个原则 第一个原则是先创建子组件再创建父组件子组件需要被“注入”到父组件中。第二个原则是先创建内层组件再创建外层组件内层组建需要被“注入”到外层组件。 最直观的做法就是将图上所有的组件按照先小后大、先内后外的顺序创建出来然后组装在一起。但这样的方式问题很大一方面组件很多可能会造成遗漏而且代码也会很冗余另一方面不利于后期的功能拓展。 为了解决这个问题我们希望找到一种通用的、统一的方法来管理组件的生命周期LifeCycle LifeCycle接口 我们把不变点抽象出来成为一个接口这个接口跟生命周期有关叫作 LifeCycle。LifeCycle 接口里应该定义这么几个方法init()、start()、stop() 和 destroy()每个具体的组件去实现这些方法。 理所当然在父组件的 init() 方法里需要创建子组件并调用子组件的 init() 方法。同样在父组件的 start() 方法里也需要调用子组件的 start() 方法因此调用者可以无差别的调用各组件的 init() 方法和 start() 方法这就是组合模式的使用并且只要调用最顶层组件也就是 Server 组件的 init() 和 start() 方法整个 Tomcat 就被启动起来了。下面是 LifeCycle 接口的定义。 LifeCycle事件 因为各个组件 init() 和 start() 方法的具体实现是复杂多变的比如在 Host 容器的启动方法里需要扫描 webapps 目录下的 Web 应用创建相应的 Context 容器。如果后续逻辑变化的话需要不断修改 start() 的方法违反了开闭原则。 我们注意到组件的 init() 和 start() 调用是由它的父组件的状态变化触发的上层组件的初始化会触发子组件的初始化上层组件的启动会触发子组件的启动因此我们把组件的生命周期定义成一个个状态把状态的转变看作是一个事件。而事件是有监听器的在监听器里可以实现一些逻辑并且监听器也可以方便的添加和删除这就是典型的观察者模式。 具体来说就是在 LifeCycle 接口里加入两个方法添加监听器和删除监听器。除此之外我们还需要定义一个 Enum 来表示组件有哪些状态以及处在什么状态会触发什么样的事件。因此 LifeCycle 接口和 LifeCycleState 就定义成了下面这样。 从图上可以看到组件的生命周期有 NEW、INITIALIZING、INITIALIZED、STARTING_PREP、STARTING、STARTED 等而一旦组件到达相应的状态就触发相应的事件比如 NEW 状态表示组件刚刚被实例化而当 init() 方法被调用时状态就变成 INITIALIZING 状态这个时候就会触发 BEFORE_INIT_EVENT 事件如果有监听器在监听这个事件它的方法就会被调用。 LifeCycleBase 抽象基类 当我们定义好了接口就要去写实现类实现它而在一个接口的不同实现类里可能很多逻辑都是一样的。那子类如何重用这部分逻辑呢常见的方法就是定义一个基类来实现共同的逻辑然后让各个子类去继承它就达到了重用的目的。 而基类中往往会定义一些抽象方法所谓的抽象方法就是说基类不会去实现这些方法而是调用这些方法来实现骨架逻辑。抽象方法是留给各个子类去实现的并且子类必须实现否则无法实例化。 LifeCycleBase 在实现 Lifecycle接口的基础上定义了如下四个抽象方法交给子类实现并在内部逻辑中调用了该方法 protected abstract void initInternal() throws LifecycleException;protected abstract void startInternal() throws LifecycleException;protected abstract void stopInternal() throws LifecycleException;protected abstract void destroyInternal() throws LifecycleException;结合下面代码进行分析 Override public final synchronized void init() throws LifecycleException {//1. 状态检查if (!state.equals(LifecycleState.NEW)) {invalidTransition(Lifecycle.BEFORE_INIT_EVENT);}try {//2. 触发 INITIALIZING 事件的监听器setStateInternal(LifecycleState.INITIALIZING, null, false);//3. 调用具体子类的初始化方法initInternal();//4. 触发 INITIALIZED 事件的监听器setStateInternal(LifecycleState.INITIALIZED, null, false);} catch (Throwable t) {...} }进行状态检查只有是 New 状态的组件才能进行 init触发 INITIALIZING 事件的监听器调用具体子类的初始化方法触发 INITIALIZED 事件的监听器 总之LifeCycleBase 调用了抽象方法来实现骨架逻辑LifeCycleBase 负责触发事件并调用监听器的方法。那是什么时候、谁把监听器注册进来的呢 Tomcat 自定义了一些监听器这些监听器是父组件在创建子组件的过程中注册到子组件 的。比如 MemoryLeakTrackingListener 监听器用来检测 Context 容器中的内存泄漏这个监听器是 Host 容器在创建 Context 容器时注册到 Context 中的。我们还可以在 server.xml 中定义自己的监听器Tomcat 在启动时会解析 server.xml 创建监听器并注册到容器组件。 总览图 2 Tomcat启动流程 1.Tomcat 本质上是一个 Java 程序因此 startup.sh 脚本会启动一个 JVM 来运行 Tomcat 的启动类 Bootstrap。 2.Bootstrap 的主要任务是初始化 Tomcat 的类加载器并且创建 Catalina。注意Tomcat和Java程序不是一个类加载器 3.Catalina 是一个启动类它通过解析 server.xml、创建相应的组件并调用 Server 的 start 方法。 4.Server 组件的职责就是管理 Service 组件它会负责调用 Service 的 start 方法。 5.Service 组件的职责就是管理连接器和顶层容器 Engine因此它会调用连接器和 Engine 的 start 方法。 这样 Tomcat 的启动就算完成了。这些启动类或者组件不处理具体请求它们的任务主要是“管理”管理下层组件的生命周期并且给下层组件分配任务也就是把请求路由到负责“干活儿”的组件。 2.1 Catalina Catalina 的主要任务就是创建 Server它需要解析 server.xml把在 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 在停止之前会尝试执行这个线程的 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 方法会释放和清理所有的资源。 2.2 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 流程。 2.3 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 在容器组件之后启动。组件停止的顺序跟启动顺序正好相反的也是基于它们的依赖关系。 2.4 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/14423597/

相关文章:

  • 做网站卖装备山东省安全双体系建设网站地址
  • 怎么不花钱建网站网页制作与网站建设》在线作业 答案
  • 网站开发周期价格wordpress禁止右键插件
  • 连云港市城乡建设管理局网站十八款禁用黄app软件
  • 网店设计美工网站seo推广计划
  • 东莞网站建设制作哪家好都有哪些网站
  • 网站关于我们介绍模板wordpress google翻译
  • wordpress qq百度seo点击
  • 外贸做网站用什么ps淘宝网页设计教程
  • 品牌网站建是啥意思简约中文网站设计欣赏
  • 网站流量如何提高长沙网络推广联系昔年下拉
  • 火花机 东莞网站建设登錄wordpress界面
  • 网站建设123autumn wordpress
  • 服饰营销型网站建设西安东郊网站建设公司
  • html5网站开发案例视频计算机网络技术电商网站建设与运营方向
  • 首钢建设网站搬瓦工装WordPress
  • 如何做外围网站的代理设计成功一个电子商务网站
  • 开发网站开发工程师招聘要求做网站推广话术
  • 随州百度网站建设兼职做彩平网站
  • 浙江省住房与和城乡建设厅网站网站建设要学哪些软件有哪些
  • 网站建设下什么科目开发公司法人和项目负责人质量安全责任制度
  • 哪些网站可以做视频收费可以免费观看电影的网站
  • 创建网站的价格郴州网站制作公司在哪里
  • wordpress电影站数据下载重庆开发
  • 个人主页界面网站搜索引擎营销简称
  • 搜狗网站seo如何做优品快报下的子网站
  • APP客户端网站建设那些网站可以给产品做推广
  • 辛集网站建设手机制作ppt的软件免费
  • 电子商务网站建设 试题图书馆网站建设方案
  • .net做网站的方式云南照明网站建设