0
点赞
收藏
分享

微信扫一扫

信息系统安全(第二章)

得一道人 2024-01-26 阅读 11

Tomcat的设计模式分析

门面设计模式

门面设计模式在 Tomcat中有多处使用,在 Request 和 Response 对象封装中Standard Wrapper 到 ServletConfig 封装中、ApplicationContext 到 ServletContext 封装中等都用到了这种设计模式

门面设计模式的原理

顾名思义,就是将一个东西封装成一个门面好与人家更容易进行交流,就像一个国家的外交部一样。

门面设计模式示意图如下:

Client 只能访问到 Façade 中提供的数据是门面设计模式的关键,至于Client 如何访问 Façade 和 Subsystem 如何提供 Façade 门面设计模式并没有规定死。

Tomcat 的门面设计模式示例

下面是 Request 上使用的门面设计模式


从图中可以看出 HttpRequestFacade 类封装了 HttpRequest 接口能够提供数据,通过 HttpRequestFacade 访问到的数据都被代理到HttpRequest 中,通常被封装的对象都被设为 Private 或者Protected 访问修饰,以防止在 Façade 中被直接访问。

观察者设计模式

观察者模式的原理

观察者模式通常包含下面这几个角色:
  • Subject 就是抽象主题:它负责管理所有观察者的引用,同时定义主要的事件操作。
  • ConcreteSubject 具体主题:它实现了抽象主题的所有定义的接口,当自己发生变
  • 化时,会通知所有观察者。
  • Observer 观察者:监听主题发生变化相应的操作接口。
Tomcat 的观察者模式示例
Lifecycle 的观察者模式结构图:



  • LifecycleEvent使得可以定义事件类别,不同的事件可区别处理,更加灵活。
  • LifecycleSupport 类代理了主题对多观察者的管理,将这个管理抽出来统一实现,以后如果修改只要修改 LifecycleSupport 类就可以了,不需要去修改所有具体主题,

因为所有具体主题的对观察者的操作都被代理给 LifecycleSupport类了。这可以认为是观察者模式的改进版。实际执行者就是LifecyleSupport去执行

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);
}

命令设计模式

命令模式的原理


下面是命令模式通常包含下面几个角色:

  • Client:创建一个命令,并决定接受者
  • Command 命令:命令接口定义一个抽象方法
  • ConcreteCommand:具体命令,负责调用接受者的相应操作
  • Invoker 请求者:负责调用命令对象执行请求
  • Receiver 接受者:负责具体实施和执行一次请求
Tomcat 中的命令模式的示例

下面看一下 Tomcat 是如何实现命令模式的结构图

  • Connector 作为抽象请求者,HttpConnector 作为具体请求者。
  • HttpProcessor 作为命令。
  • Container 作为命令的抽象接受者,ContainerBase 作为具体的接受者。
  • 客户端就是应用服务器 Server组件了。

  1. Server 首先创建命令请求者 HttpConnector 对象,创建命令 HttpProcessor 命令对象,把请求者封装到命令对象里面。

  2. 再把命令对象交给命令接受者ContainerBase 容器来处理命令。命令的最终是被 Tomcat 的Container 执行的。

  3. 命令可以以队列的方式进来,Container可以以不同的方式来处理请求,如HTTP1.0 协议和 HTTP1.1 的处理方式就会不同。


责任链模式

责任链模式的原理

通常责任链模式包含下面几个角色:

  • Handler(抽象处理者):定义一个处理请求的接口
  • ConcreteHandler(具体处理者):处理请求的具体类,或者传给下家

Tomcat中责任链模式示例

在 tomcat 中这种设计模式几乎被完整的使用,tomcat 的容器设置就是责任链模式,从 Engine 到 Host 再到 Context 一直到Wrapper 都是通过一个链传递请求
Tomcat 中责任链模式的类结构图如下:


上图基本描述了四个子容器使用责任链模式的类结构图,对应的责任链模式的角色,Container 扮演抽象处理者角色,具体处理者由StandardEngine 等子容器扮演。与标准的责任链不同的是,这里引入了 Pipeline 和 Valve 接口。他们有什么作用呢?

实际上 Pipeline 和 Valve 是扩展了这个链的功能,使得在链往下传递过程中,能够接受外界的干预。Pipeline 就是连接每个子容器的管子,里面传递的 Request 和 Response 对象好比管子里流的水,而 Valve 就是这个管子上开的一个个小口子,让你有机会能够接触到里面的水,做一些额外的事情。

为了防止水被引出来而不能流到下一个容器中,每一段管子最后总有一个节点保证它一定能流到下一个子容器,所以每个容器都有一个 StandardXXXValve。只要涉及到这种有链式是处理流程这是一个非常值得借鉴的模式。

举报

相关推荐

0 条评论