您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息

【Tomcat】Tomcat相关设计模式分析

2024/4/19 21:27:45发布5次查看
门面模式门面模式在 tomcat 中有多处使用,在 request 和 response 对象封装中、standard wrapper 到 servletconfig 封装中、applicationcontext 到 servletcontext 封装中等都用到了这种设计模式。
门面设模式的原理这么多场合都用到了这种设计模式,那这种设计模式究竟能有什么作用呢?顾名思义,就是将一个东西封装成一个门面好与人家更容易进行交流,就像一个国家的外交部一样。
这种设计模式主要用在一个大的系统中有多个子系统组成时,这多个子系统肯定要涉及到相互通信,但是每个子系统又不能将自己的内部数据过多的暴露给其它系统,不然就没有必要划分子系统了。每个子系统都会设计一个门面,把别的系统感兴趣的数据封装起来,通过这个门面来进行访问。这就是门面设计模式存在的意义。
门面设计模式示意图如下:
图 1. 门面示意图
client 只能访问到 façade 中提供的数据是门面设计模式的关键,至于 client 如何访问 façade 和 subsystem 如何提供 façade 门面设计模式并没有规定死。
tomcat 的门面模式示例tomcat 中门面设计模式使用的很多,因为 tomcat 中有很多不同组件,每个组件要相互交互数据,用门面模式隔离数据是个很好的方法。
下面是 request 上使用的门面设计模式:
图 2. request 的门面设计模式类图
从图中可以看出 httprequestfacade 类封装了 httprequest 接口能够提供数据,通过 httprequestfacade 访问到的数据都被代理到 httprequest 中,通常被封装的对象都被设为 private 或者 protected 访问修饰,以防止在 façade 中被直接访问。
观察者模式这种设计模式也是常用的设计方法通常也叫发布 - 订阅模式,也就是事件监听机制,通常在某个事件发生的前后会触发一些操作。
观察者模式的原理观察者模式原理也很简单,就是你在做事的时候旁边总有一个人在盯着你,当你做的事情是它感兴趣的时候,它就会跟着做另外一些事情。但是盯着你的人必须要到你那去登记,不然你无法通知它。观察者模式通常包含下面这几个角色:
subject 就是抽象主题:它负责管理所有观察者的引用,同时定义主要的事件操作。concretesubject 具体主题:它实现了抽象主题的所有定义的接口,当自己发生变化时,会通知所有观察者。observer 观察者:监听主题发生变化相应的操作接口。tomcat 的观察者模式示例tomcat 中观察者模式也有多处使用,前面讲的控制组件生命周期的 lifecycle 就是这种模式的体现,还有对 servlet 实例的创建、session 的管理、container 等都是同样的原理。下面主要看一下 lifecycle 的具体实现。
lifecycle 的观察者模式结构图:
图 3. lifecycle 的观察者模式结构图
上面的结构图中,lifecyclelistener 代表的是抽象观察者,它定义一个 lifecycleevent 方法,这个方法就是当主题变化时要执行的方法。 serverlifecyclelistener 代表的是具体的观察者,它实现了 lifecyclelistener 接口的方法,就是这个具体的观察者具体的实现方式。lifecycle 接口代表的是抽象主题,它定义了管理观察者的方法和它要所做的其它方法。而 standardserver 代表的是具体主题,它实现了抽象主题的所有方法。这里 tomcat 对观察者做了扩展,增加了另外两个类:lifecyclesupport、lifecycleevent,它们作为辅助类扩展了观察者的功能。lifecycleevent 使得可以定义事件类别,不同的事件可区别处理,更加灵活。lifecyclesupport 类代理了主题对多观察者的管理,将这个管理抽出来统一实现,以后如果修改只要修改 lifecyclesupport 类就可以了,不需要去修改所有具体主题,因为所有具体主题的对观察者的操作都被代理给 lifecyclesupport 类了。这可以认为是观察者模式的改进版。
lifecyclesupport 调用观察者的方法代码如下:
清单 1. lifecyclesupport 中的 firelifecycleevent 方法public void firelifecycleevent(string type, object data) { lifecycleevent event = new lifecycleevent(lifecycle, type, data); lifecyclelistener interested[] = null; synchronized (listeners) { interested = (lifecyclelistener[]) listeners.clone(); } for (int i = 0; i < interested.length; i++) interested[i].lifecycleevent(event);}
主题是怎么通知观察者呢?看下面代码:
清单 2. 容器中的 start 方法public void start() throws lifecycleexception { lifecycle.firelifecycleevent(before_start_event, null); lifecycle.firelifecycleevent(start_event, null); started = true; synchronized (services) { for (int i = 0; i < services.length; i++) { if (services[i] instanceof lifecycle) ((lifecycle) services[i]).start(); } } lifecycle.firelifecycleevent(after_start_event, null);}
来看看tomcat7中这部分的代码,上一篇文章说过组件的生命周期是由包含组件的父容器来管理的,service的启动过程就由server管理,server接口的标准实现类是standardserver类,standardserver中实现了startinernal()方法,就是循环启动standserver管理的service的过程,tomcat的service都实现了lifecycle接口,所以被管理的service都将被通知到,从而执行start()方法,startintenal()方法是这样的:
/** * start nested components ({@link service}s) and implement the requirements * of {@link org.apache.catalina.util.lifecyclebase#startinternal()}. * * @exception lifecycleexception if this component detects a fatal error * that prevents this component from being used */@overrideprotected void startinternal() throws lifecycleexception { firelifecycleevent(configure_start_event, null); setstate(lifecyclestate.starting); globalnamingresources.start(); // start our defined services synchronized (services) { for (int i = 0; i < services.length; i++) { services[i].start(); } }}
现在所有的service就会收到通知继而执行start方法。如果一个service不允许被使用将会抛出一个lifecycleexception异常。
stopintenal()会通知所有service执行stop方法,具体处理流程与startintenal()方法类似。
上面代码清单关键在firelifecycleevent()方法,其执行流程如下:
调用lifecyclebase的firelifecycleevent(lifecyclelistener listener)方法,lifecyclebase是一个抽象类,实现了lifecycle接口继续调用lifecyclesupport(是一个辅助完成对已经注册监听器的事件通知类,不可被继承,使用final)的firelifecycleevent(string type, object data)方法完成事件通知firelifecycleevent(string type, object data)的方法如下:
/** * notify all lifecycle event listeners that a particular event has * occurred for this container. the default implementation performs * this notification synchronously using the calling thread. * * @param type event type * @param data event data */public void firelifecycleevent(string type, object data) { lifecycleevent event = new lifecycleevent(lifecycle, type, data); lifecyclelistener interested[] = listeners; for (int i = 0; i < interested.length; i++) interested[i].lifecycleevent(event);}
所以,具体事件的通知是由lifecyclelistener接口的lifecycleevent方法完成的,各实现类可以根据不同的情况实现不同的事件监听逻辑。
命令模式前面把 tomcat 中两个核心组件 connector 和 container,比作一对夫妻。男的将接受过来的请求以命令的方式交给女主人。对应到 connector 和 container,connector 也是通过命令模式调用 container 的。
命令模式的原理命令模式主要作用就是封装命令,把发出命令的责任和执行命令的责任分开。也是一种功能的分工。不同的模块可以对同一个命令做出不同解释。
下面是命令模式通常包含下面几个角色:
client:创建一个命令,并决定接受者command 命令:命令接口定义一个抽象方法concretecommand:具体命令,负责调用接受者的相应操作invoker 请求者:负责调用命令对象执行请求receiver 接受者:负责具体实施和执行一次请求tomcat 中的命令模式的示例tomcat 中命令模式在 connector 和 container 组件之间有体现,tomcat 作为一个应用服务器,无疑会接受到很多请求,如何分配和执行这些请求是必须的功能。
下面看一下 tomcat 是如何实现命令模式的,下面是 tomcat 命令模式的结构图:
图 4. tomcat 命令模式的结构图
connector 作为抽象请求者,httpconnector 作为具体请求者。httpprocessor 作为命令。container 作为命令的抽象接受者,containerbase 作为具体的接受者。客户端就是应用服务器 server 组件了。server 首先创建命令请求者 httpconnector 对象,然后创建命令 httpprocessor 命令对象。再把命令对象交给命令接受者 containerbase 容器来处理命令。命令的最终是被 tomcat 的 container 执行的。命令可以以队列的方式进来,container 也可以以不同的方式来处理请求,如 http1.0 协议和 http1.1 的处理方式就会不同。
责任链模式tomcat 中一个最容易发现的设计模式就是责任链模式,这个设计模式也是 tomcat 中 container 设计的基础,整个容器的就是通过一个链连接在一起,这个链一直将请求正确的传递给最终处理请求的那个 servlet。
责任链模式的原理责任链模式,就是很多对象有每个对象对其下家的引用而连接起来形成一条链,请求在这条链上传递,直到链上的某个对象处理此请求,或者每个对象都可以处理请求,并传给下一家,直到最终链上每个对象都处理完。这样可以不影响客户端而能够在链上增加任意的处理节点。
通常责任链模式包含下面几个角色:
handler(抽象处理者):定义一个处理请求的接口concretehandler(具体处理者):处理请求的具体类,或者传给下家tomcat 中责任链模式示例在 tomcat 中这种设计模式几乎被完整的使用,tomcat 的容器设置就是责任链模式,从 engine 到 host 再到 context 一直到 wrapper 都是通过一个链传递请求。
tomcat 中责任链模式的类结构图如下:
图 5. tomcat 责任链模式的结构图
上图基本描述了四个子容器使用责任链模式的类结构图,对应的责任链模式的角色,container 扮演抽象处理者角色,具体处理者由 standardengine 等子容器扮演。与标准的责任链不同的是,这里引入了 pipeline 和 valve 接口。他们有什么作用呢?
实际上 pipeline 和 valve 是扩展了这个链的功能,使得在链往下传递过程中,能够接受外界的干预。pipeline 就是连接每个子容器的管子,里面传递的 request 和 response 对象好比管子里流的水,而 valve 就是这个管子上开的一个个小口子,让你有机会能够接触到里面的水,做一些额外的事情。
为了防止水被引出来而不能流到下一个容器中,每一段管子最后总有一个节点保证它一定能流到下一个子容器,所以每个容器都有一个 standardxxxvalve。只要涉及到这种有链式是处理流程这是一个非常值得借鉴的模式。
转至:
以上就是【tomcat】tomcat相关设计模式分析的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录