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

网站空间的权限网站建设的基本流程有哪些

网站空间的权限,网站建设的基本流程有哪些,凡科网站建设,自己制作手机app软件1. Tomcat介绍 1.1. 介绍 ‌‌‌  这边使用的是Tomcat9来做说明#xff0c;本章节先对Tomcat架构和设计有个整体认识。后续章节会对Tomcat性能调优做说明。 ‌‌‌  官方文档介绍 ‌‌‌  https://tomcat.apache.org/tomcat-9.0-doc/index.html1.2. Tomcat概念 ‌‌…1. Tomcat介绍 1.1. 介绍 ‌‌‌  这边使用的是Tomcat9来做说明本章节先对Tomcat架构和设计有个整体认识。后续章节会对Tomcat性能调优做说明。 ‌‌‌  官方文档介绍 ‌‌‌  https://tomcat.apache.org/tomcat-9.0-doc/index.html 1.2. Tomcat概念 ‌‌‌  Tomcat是Apache Software FoundationApache软件基金会开发的一款开源的Java Servlet容器。它是一种Web服务器用于在服务器端运行Java Servlet和JavaServer Pages (JSP)技术。它可以为Java Web应用程序提供运行环境并通过HTTP协议处理客户端请求。Tomcat也支持多种Web应用程序开发技术例如JavaServer Faces (JSF)、Java Persistence API (JPA)等。总的来说Tomcat是一款高效、稳定和易于使用的Web服务器。 ‌‌‌  Tomcat核心 Http服务器Servlet容器。 1.3. Tomcat目录结构 ‌‌‌  Tomcat的解压之后的目录可以看到如下的目录结构。 ‌‌‌  binbin目录主要是用来存放tomcat的脚本如startup.sh , shutdown.shconfcatalina.policy: Tomcat安全策略文件,控制JVM相关权限,具体可以参考java. security.Permissioncatalina.properties : Tomcat Catalina行为控制配置文件,比如Common ClassLoaderlogging.properties : Tomcat日志配置文件, JDK Logging server.xml : Tomcat Server配置文件GlobalNamingResources :全局JNDI资源context.xml :全局Context配置文件tomcat-users.xml : Tomcat角色配置文件web.xml : Servlet标准的web.xml部署文件, Tomcat默认实现部分配置入内:org.apache.catalina.servlets.DefaultServletorg.apache.jasper.servlet.JspServletlib公共类库logstomcat在运行过程中产生的日志文件webapps用来存放应用程序当tomcat启动时会去加载webapps目录下的应用程序work用来存放tomcat在运行时的编译后文件例如JSP编译后的文件‌‌1.4. web应用部署的三种方式 ‌‌‌‌‌‌  Tomcat的web应用支持war包部署文件夹部署描述符部署。 1.4.1. war包部署和文件夹部署 ‌‌‌  默认情况下项目war包和文件夹拷贝到webapps目录下就行。war包会自动解压成war包名称的文件夹。 ‌‌‌   ‌‌‌  该目录跟Host标签的appBase有关。 ‌‌‌ ‌‌‌  //指定appBase ‌‌‌  Host namelocalhost appBasewebapps unpackWARstrue autoDeploytrue ‌‌‌  autoDeploy表示支持热部署。 1.4.2. 描述符部署 ‌‌‌  在server.xml 的Context标签下配置Context。比如下面这样比较常用的描述符部署。 ‌‌‌  Context docBaseD:\mvc path/mvc reloadabletrue / ‌‌‌  path指定访问该Web应用的URL入口context-path。 ‌‌‌  docBase指定Web应用的文件路径可以给定绝对路径也可以给定相对于Host的appBase属性的相对路径。 ‌‌‌  reloadable如果这个属性设为true支持热加载tomcat服务器在运行状态下会监视在WEB-INF/classes和WEB-INF/lib目录下class文件的改动如果监测到有class文件被更新的服务器会自动重新加载Web应用。 1.4.3. 比较特殊的部署 ‌‌‌  在$CATALINA_BASE/conf/[enginename]/[hostname]/ 目录下默认conf/Catalina/localhost创建xml文件文件名就是contextPath。比如创建mvc.xmlpath就是/mvc。 ‌‌‌  这种方式不需要重启应用就可以部署应用。 ‌‌‌  Context docBaseD:\mvc reloadabletrue / ‌‌‌  注意 ‌‌‌  想要根路径访问文件名就设置为ROOT.xml。 2. Tomcat整体架构分析 ‌‌‌  Tomcat 要实现 2 个核心功能 ‌‌‌  处理 Socket 连接负责网络字节流与 Request 和 Response 对象的转化。 ‌‌‌  加载和管理 Servlet以及具体处理 Request 请求。 ‌‌‌  因此 Tomcat 设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流容器负责内部处理。 2.1. Tomcat架构图 ‌‌‌  Tomcat的架构分为以下几个部分 ‌‌‌  1. ConnectorTomcat的连接器用于接收请求并将其发送给容器。 ‌‌‌  2. ContainerTomcat的容器负责管理Servlet、JSP和静态资源的生命周期。 ‌‌‌  3. EngineTomcat的引擎管理容器的生命周期和分配请求。 ‌‌‌  4. HostTomcat的主机可以管理多个Web应用程序。 ‌‌‌  5. ContextTomcat的上下文用于管理单个Web应用程序的配置信息。 ‌‌‌  6. ServletTomcat的Servlet负责处理请求并生成响应。 ‌‌‌  7. JSPTomcat的JSP用于动态生成Web内容。 ‌‌‌  总的来说Tomcat的架构是一个分层的架构每一层都有其自己的功能和职责。该架构可以提高Tomcat的性能和可维护性并使得Tomcat可以支持大量的Java Web应用程序。 ‌‌‌  其中四大容器分别是EngineHostContextWrapper。其标准实现分别有StandardEngineStandardHostStandardContextStandardWrapper都实现了org.apache.catalina.Container接口。 2.2. Tomcat核心组件详解 2.2.1. Server 组件 ‌‌‌  指的就是整个 Tomcat 服务器包含多组服务Service负责管理和启动各个Service同时监听8005端口发过来的 shutdown 命令用于关闭整个容器 。 2.2.2. Service组件 ‌‌‌  每个 Service 组件都包含了若干用于接收客户端消息的 Connector 组件和处理请求的 Engine 组件。 Service 组件还包含了若干 Executor 组件每个 Executor 都是一个线程池它可以为 Service内所有组件提供线程池执行任务。 Tomcat 内可能有多个 Service这样的设计也是出于灵活性的考虑。通过在Tomcat 中配置多个 Service可以实现通过不同的端口号来访问同一台机器上部署的不同应用。 2.2.3. 连接器Connector组件 ‌‌‌  Tomcat 与外部世界的连接器监听固定端口接收外部请求传递给 Container并将Container处理的结果返回给外部。连接器对 Servlet 容器屏蔽了不同的应用层协议及 I/O 模型无论是 HTTP还是 AJP在容器中获取到的都是一个标准的 ServletRequest 对象。 2.2.4. 容器Container组件 ‌‌‌  容器顾名思义就是用来装载东西的器具在 Tomcat 里容器就是用来装载 Servlet 的。 ‌‌‌  Tomcat 通过一种分层的架构使得 Servlet 容器具有很好的灵活性。Tomcat 设计了 4 种容器分别是 Engine、Host、Context 和 Wrapper。这 4 种容器不是平行关系而是父子关系。 ‌‌‌  Engine引擎Servlet 的顶层容器用来管理多个虚拟站点一个 Service 最多只能有一个 Engine。 ‌‌‌  Host虚拟主机负责 web 应用的部署和 Context 的创建。可以给 Tomcat配置多个虚拟主机地址而一个虚拟主机下可以部署多个 Web 应用程序。 ‌‌‌  ContextWeb 应用上下文包含多个 Wrapper负责 web 配置的解析、管理所有的 Web 资源。一个Context对应一个 Web 应用程序。 ‌‌‌  Wrapper表示一个 Servlet最底层的容器是对 Servlet 的封装负责 Servlet 实例的创建、执行和销毁。 2.3. 结合Server.xml理解Tomcat架构 ‌‌‌  以通过 Tomcat 的 server.xml 配置文件来加深对 Tomcat 架构的理解。Tomcat 采用了组件化的设计它的构成组件都是可配置的其中最外层的是 Server其他组件按照一定的格式要求配置在这个顶层容器中。 Server //顶层组件可以包括多个ServiceService //顶层组件可包含一个Engine多个连接器Connector///连接器组件代表通信接口Engine//容器组件一个Engine组件处理Service中的所有请求包含多个HostHost //容器组件处理特定的Host下客户请求可包含多个ContextContext/ //容器组件为特定的Web应用处理所有的客户请求/Host/Engine/Service /Server ‌‌‌  Tomcat启动期间会通过解析 server.xml利用反射创建相应的组件所以xml中的标签和源码一一对应。 2.4. 请求定位 Servlet 的过程 ‌‌‌  Tomcat 是用 Mapper 组件来完成这个任务的。Mapper 组件的功能就是将用户请求的 URL 定位到一个 Servlet它的工作原理是Mapper 组件里保存了 Web 应用的配置信息其实就是容器组件与访问路径的映射关系比如 Host 容器里配置的域名、Context 容器里的 Web 应用路径以及Wrapper 容器里 Servlet 映射的路径你可以想象这些配置信息就是一个多层次的 Map。当一个请求到来时Mapper 组件通过解析请求 URL 里的域名和路径再到自己保存的 Map 里去查找就能定位到一个 Servlet。一个请求 URL 最后只会定位到一个 Wrapper 容器也就是一个 Servlet。 3. Tomcat架构设计精髓分析 3.1. Connector高内聚低耦合设计 ‌‌‌  优秀的模块化设计应该考虑高内聚、低耦合 ‌‌‌  高内聚是指相关度比较高的功能要尽可能集中不要分散。 ‌‌‌  低耦合是指两个相关的模块要尽可能减少依赖的部分和降低依赖的程度不要让两个模块产生强依赖。 ‌‌‌  Tomcat连接器需要实现的功能 ‌‌‌  监听网络端口(三次握手)。 ‌‌‌  接受网络连接请求。 ‌‌‌  读取请求网络字节流。 ‌‌‌  根据具体应用层协议HTTP/AJP解析字节流生成统一的 Tomcat Request 对象。 ‌‌‌  将 Tomcat Request 对象转成标准的 ServletRequest。 ‌‌‌  调用 Servlet 容器得到 ServletResponse。 ‌‌‌  将 ServletResponse 转成 Tomcat Response 对象。 ‌‌‌  将 Tomcat Response 转成网络字节流。 ‌‌‌  将响应字节流写回给浏览器。 ‌‌‌  分析连接器详细功能列表我们会发现连接器需要完成 3 个高内聚的功能 ‌‌‌  网络通信。 ‌‌‌  应用层协议解析。 ‌‌‌  Tomcat Request/Response 与 ServletRequest/ServletResponse 的转化。 ‌‌‌  因此 Tomcat 的设计者设计了 3 个组件来实现这 3 个功能分别是 EndPoint、Processor 和 ‌‌‌  Adapter。 ‌‌‌  EndPoint 负责提供字节流给 Processor。 ‌‌‌  Processor 负责提供 Tomcat Request 对象给 Adapter。 ‌‌‌  Adapter 负责提供 ServletRequest 对象给容器。 ‌‌‌  注意 ‌‌‌  组件之间通过抽象接口交互。这样做的好处是封装变化。这是面向对象设计的精髓将系统中经常变化的部分和稳定的部分隔离有助于增加复用性并降低系统耦合度。 ‌‌‌  由于 I/O 模型和应用层协议可以自由组合比如 NIO HTTP 或者 NIO2 AJP。Tomcat的设计者将网络通信和应用层协议解析放在一起考虑设计了一个叫 ProtocolHandler 的接口来封装这两种变化点。各种协议和通信模型的组合有相应的具体实现类。比如Http11NioProtocol 和AjpNioProtocol。 ‌‌‌  除了这些变化点系统也存在一些相对稳定的部分因此 Tomcat 设计了一系列抽象基类来封装这些稳定的部分抽象基类 AbstractProtocol 实现了 ProtocolHandler 接口。每一种应用层协议有自己的抽象基类比如 AbstractAjpProtocol 和 AbstractHttp11Protocol具体协议的实现类扩展了协议层抽象基类。 ‌‌‌  NIO2就是AIO。 ‌‌‌  APR是早期没有NIO通过调用操作系统动态链接库实现该效果。 ‌‌‌  AJP早期时候Apache可以反向代理到TomcatApache跟Tomcat通信就用AJP协议。 ‌‌‌3.1.2. ProtocolHandler ‌‌‌  连接器用 ProtocolHandler 来处理网络连接和应用层协议包含了 2 个重要部件EndPoint 和Processor。 连接器用 ProtocolHandler 接口来封装通信协议和 I/O 模型的差异ProtocolHandler 内部又分为 EndPoint 和 Processor 模块EndPoint 负责底层 Socket 通信Proccesor 负责应用层协议解析。连接器通过适配器 Adapter 调用容器。 ‌‌‌‌‌‌3.1.2.1. EndPoint ‌‌‌  EndPoint 是通信端点即通信监听的接口是具体的 Socket 接收和发送处理器是对传输层的抽象因此 EndPoint 是用来实现 TCP/IP 协议的。 ‌‌‌  EndPoint 是一个接口对应的抽象实现类是 AbstractEndpoint而 AbstractEndpoint 的具体子类比如在 NioEndpoint 和 Nio2Endpoint 中有两个重要的子组件Acceptor 和SocketProcessor。其中 Acceptor 用于监听 Socket 连接请求。SocketProcessor 用于处理接收到的Socket 请求它实现 Runnable 接口在 Run 方法里调用协议处理组件 Processor 进行处理。为了提高处理能力SocketProcessor 被提交到线程池来执行而这个线程池叫作执行器Executor)。 ‌‌‌  NIO的对应的类还会创建Ploller线程里头有多路复用选择器处理连接上来的socket的读写。 ‌‌3.1.1.2. Processor ‌‌‌  Processor 用来实现 HTTP/AJP 协议Processor 接收来自 EndPoint 的 Socket读取字节流解析成 Tomcat Request 和 Response 对象并通过 Adapter 将其提交到容器处理Processor 是对应用层协议的抽象。 ‌‌‌  Processor 是一个接口定义了请求的处理等方法。它的抽象实现类 AbstractProcessor 对一些协议共有的属性进行封装没有对方法进行实现。具体的实现有 AJPProcessor、HTTP11Processor等这些具体实现类实现了特定协议的解析方法和请求处理方式。 ‌‌‌  EndPoint 接收到 Socket 连接后生成一个 SocketProcessor 任务提交到线程池去处理SocketProcessor 的 Run 方法会调用 Processor 组件去解析应用层协议Processor 通过解析生成Request 对象后会调用 Adapter 的 Service 方法。 ‌‌‌‌‌‌3.1.2. Adapter(适配器) ‌‌‌  由于协议不同客户端发过来的请求信息也不尽相同Tomcat 定义了自己的 Request 类来“存放”这些请求信息。ProtocolHandler 接口负责解析请求并生成 Tomcat Request 类。但是这个 Request 对象不是标准的 ServletRequest也就意味着不能用 Tomcat Request 作为参数来调用容器。Tomcat 设计者的解决方案是引入 CoyoteAdapter这是适配器模式的经典运用连接器调用 CoyoteAdapter 的 Sevice 方法传入的是 Tomcat Request 对象CoyoteAdapter 负责将 Tomcat Request 转成 ServletRequest再调用容器的 Service 方法。 ‌‌‌  设计复杂系统的基本思路 ‌‌‌  首先要分析需求根据高内聚低耦合的原则确定子模块然后找出子模块中的变化点和不变点用接口和抽象基类去封装不变点在抽象基类中定义模板方法让子类自行实现抽象方法也就是具体子类去实现变化点。 3.2. 父子容器组合模式设计 ‌‌‌  思考Tomcat 设计了 4 大容器分别是 Engine、Host、Context 和 WrapperTomcat 是怎么管理这些容器的 ‌‌‌  Tomcat 采用组合模式来管理这些容器。具体实现方法是所有容器组件都实现了 Container 接口因此组合模式可以使得用户对单容器对象和组合容器对象的使用具有一致性。 ‌‌‌  Container 接口定义如下 ‌‌‌  public interface Container extends Lifecycle {public void setName(String name);public Container getParent();public void setParent(Container container);public void addChild(Container child);public void removeChild(Container child);public Container findChild(String name); ‌‌‌  } 3.3. Pipeline-Valve 责任链模式设计 ‌‌‌  连接器中的 Adapter 会调用容器的 Service 方法来执行 Servlet最先拿到请求的是 Engine 容器Engine 容器对请求做一些处理后会把请求传给自己子容器 Host 继续处理依次类推最后这个请求会传给 Wrapper 容器Wrapper 会调用最终的 Servlet 来处理。那么这个调用过程具体是怎么实现的呢答案是使用 Pipeline-Valve 管道。 ‌‌‌  Pipeline-Valve 是责任链模式责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理每个处理者负责做自己相应的处理处理完之后将再调用下一个处理者继续处理。 ‌‌‌  为什么要使用管道机制 ‌‌‌  在一个比较复杂的大型系统中如果一个对象或数据流需要进行繁杂的逻辑处理我们可以选择在一个大的组件中直接处理这些繁杂的业务逻辑 这个方式虽然达到目的但扩展性和可重用性较差 因为可能牵一发而动全身。更好的解决方案是采用管道机制用一条管道把多个对象(阀门部件)连接起来整体看起来就像若干个阀门嵌套在管道中一样而处理逻辑放在阀门上。 ‌‌‌  场景 ‌‌‌  1. 比如要对符合的IP进行黑白名单过滤可以在host层加个阀门过滤。 ‌‌‌  2. 请求日志处理。 3.3.1. Vavle接口设计 ‌‌‌  理解它的设计第一步就是阀门设计。Valve 表示一个处理点比如权限认证和记录日志。 ‌‌‌  public interface Valve {public Valve getNext();public void setNext(Valve valve);public void invoke(Request request, Response response) throws IOException, ServletException; ‌‌‌  } ‌‌‌  阀门的创建 ‌‌‌  阀门可以在Tomcat项目根目录-config-server.xml-对应容器标签下-自定义标签也就是当前容器的一个阀门对应到一个阀门类。请求进来后它会执行这个类实例的invoke方法。 ‌‌‌  例如 ‌‌‌  给Host容器加阀门。 ‌‌‌  1. 添加阀门标签。 Host namelocalhost appBasewebappsunpackWARstrue autoDeploytrueValve classNamecom.liu.TestValue//Host ‌‌‌  2. 创建阀门类在Tomcat源码根目录-java目录-自定义包名创建阀门类需要继承org.apache.catalina.valves.RequestFilterValve。 package com.liu;import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.RequestFilterValve; import org.apache.juli.logging.Log;import javax.servlet.ServletException; import java.io.IOException;/*** author liuYangHong* version 1.0* description:* date 2023/1/8 17:42*/ public class TestValue extends RequestFilterValve {Overridepublic void invoke(Request request, Response response) throws IOException, ServletException {System.out.println(自己处理些东西);getNext().invoke(request,response);}Overrideprotected Log getLog() {return null;} } 3.3.2. Pipline接口设计 ‌‌‌  由于Pipline是为容器设计的所以它在设计时加入了一个Contained接口, 就是为了制定当前Pipline所属的容器。 ‌‌‌  public interface Pipeline extends Contained {// 基础的处理阀public Valve getBasic();public void setBasic(Valve valve);// 对节点阀门增删查public void addValve(Valve valve);public Valve[] getValves();public void removeValve(Valve valve);// 获取第一个节点遍历的起点所以需要有这方法public Valve getFirst();// 是否所有节点阀门都支持处理Servlet3异步处理public boolean isAsyncSupported();// 找到所有不支持Servlet3异步处理的阀门public void findNonAsyncValves(SetString result); ‌‌‌  } ‌‌‌  Pipeline 中维护了 Valve 链表Valve 可以插入到 Pipeline 中对请求做某些处理。整个调用链的触发是 Valve 来完成的Valve 完成自己的处理后调用 getNext.invoke() 来触发下一个 Valve 调用。每一个容器都有一个 Pipeline 对象只要触发这个 Pipeline 的第一个 Valve这个容器里 Pipeline 中的 Valve 就都会被调用到。Basic Valve 处于 Valve 链表的末端它是 Pipeline 中必不可少的一个 Valve负责调用下层容器的 Pipeline 里的第一个 Valve。 ‌‌‌  整个调用过程由连接器中的 Adapter 触发的它会调用 Engine 的第一个 Valve ‌‌‌  //org.apache.catalina.connector.CoyoteAdapter#service ‌‌‌  // Calling the container ‌‌‌  connector.getService().getContainer().getPipeline().getFirst().invoke(request, response); ‌‌‌  Wrapper 容器的最后一个 Valve 会创建一个 Filter 链并调用 doFilter() 方法最终会调到 Servlet 的 service 方法。 ‌‌‌  //org.apache.catalina.core.StandardWrapperValve#invoke ‌‌‌  filterChain.doFilter(request.getRequest(), response.getResponse()); ‌‌‌3.3.2.1. Valve 和 Filter 的区别 ‌‌‌  Valve 是 Tomcat 的私有机制与 Tomcat 的基础架构 /API 是紧耦合的。Servlet API 是公有的标准所有的 Web 容器包括 Jetty 都支持 Filter 机制。 ‌‌‌  Valve 工作在 Web 容器级别拦截所有应用的请求而 Servlet Filter 工作在应用级别只能拦截某个 Web 应用的所有请求。 ‌‌‌  对比两种责任链模式 ‌‌‌  Filter递归方法方式取数组的Filter调用(没取完就继续取方式一个个调用数组后面元素。 3.4. Tomcat生命周期设计 ‌‌‌  通过对Tomcat架构的分析我们知道了Tomcat 都有哪些组件组件之间是什么样的关系以及 Tomcat 是怎么处理一个 HTTP 请求的。如果想让Tomcat能够对外提供服务我们需要创建、组装并启动Tomcat组件在服务停止的时候我们还需要释放资源销毁Tomcat组件这是一个动态的过程。Tomcat 需要动态地管理这些组件的生命周期。 ‌‌‌  在我们实际的工作中如果你需要设计一个比较大的系统或者框架时你同样也需要考虑这几个问题如何统一管理组件的创建、初始化、启动、停止和销毁如何做到代码逻辑清晰如何方便地添加或者删除组件如何做到组件启动和停止不遗漏、不重复 3.4.1. 一键式启停LifeCycle 接口 ‌‌‌  系统设计就是要找到系统的变化点和不变点。这里的不变点就是每个组件都要经历创建、初始化、启动这几个过程这些状态以及状态的转化是不变的。而变化点是每个具体组件的初始化方法也就是启动方法是不一样的。因此我们把不变点抽象出来成为一个接口这个接口跟生命周期有关叫作 LifeCycle。LifeCycle 接口里应该定义这么几个方法init()、start()、stop() 和 destroy()每个具体的组件去实现这些方法。 ‌‌‌  public interface Lifecycle {/** 第1类针对监听器在对应流程状态下触发对应事件 **/// 添加监听器public void addLifecycleListener(LifecycleListener listener);// 获取所有监听器public LifecycleListener[] findLifecycleListeners();// 移除某个监听器public void removeLifecycleListener(LifecycleListener listener);/** 第2类针对控制流程 **/// 初始化方法public void init() throws LifecycleException;// 启动方法public void start() throws LifecycleException;// 停止方法和start对应public void stop() throws LifecycleException;// 销毁方法和init对应public void destroy() throws LifecycleException;/** 第3类针对状态比如在启动前启动后做一些事这边记录状态**/// 获取生命周期状态public LifecycleState getState();// 获取字符串类型的生命周期状态public String getStateName(); ‌‌‌  } ‌‌‌  在父组件的 init() 方法里需要创建子组件并调用子组件的 init() 方法。同样在父组件的 start() 方法里也需要调用子组件的 start() 方法因此调用者可以无差别的调用各组件的 init() 方法和 start() 方法这就是组合模式的使用并且只要调用最顶层组件也就是 Server 组件的 init() 和 start() 方法整个 Tomcat 就被启动起来了。 3.4.2. 可扩展性LifeCycle 事件 ‌‌‌  因为各个组件 init() 和 start() 方法的具体实现是复杂多变的比如在 Host 容器的启动方法里需要扫描 webapps 目录下的 Web 应用创建相应的 Context 容器如果将来需要增加新的逻辑直接修改 start() 方法这样会违反开闭原则那如何解决这个问题呢开闭原则说的是为了扩展系统的功能你不能直接修改系统中已有的类但是你可以定义新的类。 ‌‌‌  组件的 init() 和 start() 调用是由它的父组件的状态变化触发的上层组件的初始化会触发子组件的初始化上层组件的启动会触发子组件的启动因此我们把组件的生命周期定义成一个个状态把状态的转变看作是一个事件。而事件是有监听器的在监听器里可以实现一些逻辑并且监听器也可以方便的添加和删除这就是典型的观察者模式当一个对象的状态发生改变时其所有依赖者都会收到通知并自动更新。。 ‌‌‌  具体来说就是在 LifeCycle 接口里加入两个方法添加监听器和删除监听器。 3.4.3. 重用性LifeCycleBase 抽象基类(解决代码共同逻辑地方) ‌‌‌  有了接口我们就要用类去实现接口。一般来说实现类不止一个不同的类在实现接口时往往会有一些相同的逻辑如果让各个子类都去实现一遍就会有重复代码。那子类如何重用这部分逻辑呢其实就是定义一个基类来实现共同的逻辑然后让各个子类去继承它就达到了重用的目的。而基类中往往会定义一些抽象方法所谓的抽象方法就是说基类不会去实现这些方法而是调用这些方法来实现骨架逻辑。抽象方法是留给各个子类去实现的并且子类必须实现否则无法实例化。 ‌‌‌  Tomcat 定义一个基类 LifeCycleBase 来实现 LifeCycle 接口把一些公共的逻辑放到基类中去比如生命状态的转变与维护、生命周期事件的触发以及监听器的添加和删除等而子类就负责实现自己的初始化、启动和停止等方法。为了避免跟基类中的方法同名我们把具体子类的实现方法改个名字在后面加上 Internal叫 initInternal()、startInternal() 等。   LifeCycleBase 实现了 LifeCycle 接口中所有的方法还定义了相应的抽象方法交给具体子类去实现这是典型的模板设计模式骨架抽象类和模板方法。 ‌‌‌  LifeCycleBase 的 init() 方法实现 ‌‌‌  思考是什么时候、谁把监听器注册进来的呢 ‌‌‌  Tomcat 自定义了一些监听器这些监听器是父组件在创建子组件的过程中注册到子组件的。比如 MemoryLeakTrackingListener监听器用来检测 Context 容器中的内存泄漏这个监听器是 Host 容器在创建 Context 容器时注册到 Context 中的。 ‌‌‌  监听器的添加可以在 server.xml 的Server标签下定义自己的监听器监听器可以监听对应状态执行逻辑。Tomcat 在启动时会解析 server.xml创建监听器并注册到容器组件。 3.4.4. 生命周期总体类图 StandardServer、StandardService 是 Server 和 Service 组件的具体实现类它们都继承了 LifeCycleBase。 StandardEngine、StandardHost、StandardContext 和 StandardWrapper 是相应容器组件的具体实现类因为它们都是容器所以继承了 ContainerBase 抽象基类而 ContainerBase 实现了 Container 接口也继承了 LifeCycleBase 类它们的生命周期管理接口和功能接口是分开的这也符合设计中接口分离的原则。 ‌‌‌ ‌‌‌  Tomcat 为了实现一键式启停以及优雅的生命周期管理并考虑到了可扩展性和可重用性将面向对象思想和设计模式发挥到了极致分别运用了组合模式、观察者模式、骨架抽象类和模板方法。 ‌‌‌  如果你需要维护一堆具有父子关系的实体可以考虑使用组合模式。 ‌‌‌  观察者模式听起来“高大上”其实就是当一个事件发生后需要执行一连串更新操作。传统的实现方式是在事件响应代码里直接加更新逻辑当更新逻辑加多了之后代码会变得臃肿并且这种方式是紧耦合的、侵入式的。观察者模式实现了低耦合、非侵入式的通知与更新机制。 ‌‌‌  模板方法在抽象基类中经常用到用来实现通用逻辑。 5. 思路总结 ‌‌‌  Tomcat是Http服务器Servlet容器是Web服务器用于服务端运行Servlet和JSP的技术也支持很多web应用程序开发技术如JPA,JSF等。 ‌‌‌  应用部署方式主要分为war部署文件夹部署描述符部署(在server.xml中配置部署)。 ‌‌‌  描述符部署下可以通过配置host 和Context部署应用涉及docbaseappbasepath的设置。 ‌‌‌  还有一种特别就是在$CATALINA_BASE/conf/[enginename]/[hostname]/ 目录创建xml部署。 ‌‌‌  Tomcat启动流程通过脚本调用Bootstrap的main方法解析Server.xml的个节点使用Digester解析节点组件容器监听器等转成对象。初始化组件和容器启动组件和容器。 ‌‌‌  Tomcat处理请求流程请求进来处理 Socket 连接借助Socket读取字节流根据协议将字节流与转换成Request对象最终转成ServletRequest的对象。加载和管理Servlet对象将ServletRequest的对象做为参数调用其service的方法。Servlet对象的service方法进行请求逻辑处理。请求逻辑处理完将Servlet响应数据最终适配转成Tomcat的Response对象转成响应字节流将响应字节流写回给浏览器。 ‌‌‌  Tomcat涉及两个核心组件连接器(Connector)和容器(Container)来分别做这两件事情。连接器负责对外交流读取通信内容将网络字节流到ServletRequest/ServletResponse对象之间的转换容器负责ServletRequest/ServletResponse和Servlet的之间的交互的内部处理。 ‌‌‌  连接器(Connector)主要处理功能分为网络通信应用层协议解析Tomcat Request/Response 与 ServletRequest/ServletResponse 的转化。 ‌‌‌  Tomcat 的设计者设计了 3 个组件来实现这 3 个功能分别是 EndPoint、Processor 和Adapter。 ‌‌‌  EndPoint负责Socket的网络通信处理Socket连接。 ‌‌‌  Processor负责处理网络协议读取网络字节流流解析成 Tomcat Request 和 Response 对象并通过 Adapter 将其提交到容器处理。 ‌‌‌  Adapter适配器负责将Tomcat Request 对象转成ServletRequest对象交给Servlert。 ‌‌‌  Tomcat连接器ProtocolHandler包含了EndPoint 和Processor。就是高内聚低耦合的原则将相关功能整合在一个子模块下通过接口或者抽象基类的方式分离出不变点子模块按照模板方法动态实现自己功能可变点。 ‌‌‌  Adapter使用了责任链模式每个容器都有自己的管道管道当中有自己阀门Value可以自定义阀门Value在Servlet的容器节点下配置。阀门本质就是类似单向链表有头尾节点。容器按照父子级的关系先走一遍管道的阀门在转交给下级容器管道的第一个阀门。第一个容器Engine阀门由Adapter调用Wrapper容器走完阀门会调用过滤链在调用Servlet的service()。 ‌‌‌  Container容器顾名思义就是用来装载东西的器具在 Tomcat 里容器就是用来装载 Servlet 的。Tomcat的四大容器是Engine Host Context Wrapper 它们是父子容器关系Wrapper是对 Servlet 的封装负责 Servlet 实例的创建、执行和销毁。 ‌‌‌  Tomcat使用了组合模式设计这些容器就是一个接口定义了模板方法容器实现这些方法、能操作父子容器。 ‌‌‌  Tomcat的生命周期设计使用接口分离原则一个接口定义生命周期流程添加监听器的方法和获取流程状态用个枚举定义生命周期流程里头很多状态容器实现对应生命周期流程的方法里头会判断流程状态调用该状态下对应的监听事件。
http://www.dnsts.com.cn/news/233804.html

相关文章:

  • 网站开发实训新的体会重庆信息网官网
  • 网站备案是先做网站上线还是九江seo
  • 自己怎么建设收费电影网站学校网站制作平台
  • 自适应 网站建筑安全网
  • 深圳网站策划推广杭州多语言网站建设
  • 宁波网站建设信任荣盛网络房地产建筑公司网站
  • 网站建设预付流程企业网站建设的一般要素有
  • 电脑什么软件做短视频网站网站制作书籍推荐
  • 网页设计与网站建设实例教程答案全景制作软件app
  • 网站建设案例新闻做硅胶的网站
  • 网站设计毕业设计网络销售怎么样
  • 临汾做网站电话做网站建设公司网站设计
  • 网站素材资源信息系统项目管理高级
  • 东莞网站建设化工百度账号中心
  • 网站设计 专业国内购物网站排名
  • 云南哪有网站建设推广如何用图片做网站背景
  • 有用node.js做的网站吗深圳医学科学院
  • 应用下载app排行榜阳江企业网站排名优化
  • 导视标识设计石家庄seo优化
  • 2021给个最新网站设计网站建站
  • 怎么用默认程序做网站wordpress主题Linkedin
  • 网站主机有什么用有电脑网站怎样建手机号码
  • 外贸网站哪家好360网站图标怎么做的
  • 商洛网站建设哪家好做生意在哪个网站做
  • 三网合一网站建设合同开发一个app多少钱
  • 阿里百川 网站开发wordpress折叠代码
  • 站酷网素材图库免费下载阿里巴巴官网首页1688
  • 什么类型的网站无投入网站推广
  • 中介网站设计手机网页代码
  • 网站建设发布教程视频一级a做爰视频安全网站