这里看下tomcat中责任链模式的使用。首先看下什么是责任链模式,责任链模式是抽象的处理者和具体的处理者组成。而具体处理者都拥有其下家的应用,从而形成处理链。直到有处理者处理,并且可以任意扩展链的长度。从简单点的开始,在阎宏《java与模式》一书中,有一个击鼓传花的例子。对责任链模式有很好的讲解,这里就不啰嗦了。通过书中例子,应该可以理解责任链的处理方式,这里主要看下tomcat中的使用。
首先我们来看下tomcat的配置文件,在conf/server.xml里面。
这个事原始配置文件:
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
按照需求更改后的<Engine></Engine>以内的配置文件,其他部分没有变动:
<Host name="wap.**.cc" appBase="d:/test/wapPortal" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context crossContext="true" debug="5" displayName="tawap" docBase="d:/test/wapPortal" path="" reloadable="true">
<Resource auth="Container" name="jdbc/wapportal" type="javax.sql.DataSource" maxWait="10000" maxIdle="30" maxActive="100" username="root" password="admin" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/onetouch?useUnicode=true&characterEncoding=UTF-8"/>
<ResourceLink global="jdbc/wapportal" name="jdbc/wapportal" type="javax.sql.DataSource"/>
</Context>
</Host>
<Host name=www.**.com appBase="d:/test" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context path="/" reloadable="true" docBase="d:/test">
</Context>
</Host>
tomcat对这部分的处理,就是采用责任链的模式。接下来看下实现责任链的类关系,如图:
那么从tomcat哪部分是配置文件呢?我们看下StandardService代码
public class StandardService implements Lifecycle, Service, MBeanRegistration
依照责任链模式,显然和UML图中的不属于同一个类别,所以其他的部分不构成责任链。由责任链的定义,我们主要看下其上家和下家的定义。
1.首先StandardEngine类:
//setParent方法(上家),可以看出是没有上家的
public void setParent(Container container) {
throw new IllegalArgumentException
(sm.getString("standardEngine.notParent"));
}
//addChild方法如下(下家),可以看到Host为其下家
public void addChild(Container child) {
if (!(child instanceof Host))
throw new IllegalArgumentException
(sm.getString("standardEngine.notHost"));
super.addChild(child);
}
//有必要设置默认值
public void setDefaultHost(String host) {
String oldDefaultHost = this.defaultHost;
if (host == null) {
this.defaultHost = null;
} else {
this.defaultHost = host.toLowerCase();
}
support.firePropertyChange("defaultHost", oldDefaultHost,
this.defaultHost);
}
2.依照这个顺序,很明显接下来看下Host了。
//下家为Context
public void addChild(Container child) {
if (child instanceof Lifecycle) {
((Lifecycle) child).addLifecycleListener(
new MemoryLeakTrackingListener());
}
if (!(child instanceof Context))
throw new IllegalArgumentException
(sm.getString("standardHost.notContext"));
super.addChild(child);
}
3.Context的处理,standContext类中addChild方法,可以从代码中看出下家是Wrapper。
Wrapper oldJspServlet = null;
if (!(child instanceof Wrapper)) {
throw new IllegalArgumentException
(sm.getString("standardContext.notWrapper"));
}
Wrapper wrapper = (Wrapper) child;
4.Wrapper对应实现
//可以看到这层到了责任链处理的终点了
public void addChild(Container child) {
throw new IllegalStateException
(sm.getString("standardWrapper.notChild"));
}
//该类中还限制了其上家
public void setParent(Container container) {
if ((container != null) &&
!(container instanceof Context))
throw new IllegalArgumentException
(sm.getString("standardWrapper.notContext"));
if (container instanceof StandardContext) {
swallowOutput = ((StandardContext)container).getSwallowOutput();
unloadDelay = ((StandardContext)container).getUnloadDelay();
}
super.setParent(container);
}
tomcat启动的时候,是肯定要从配置文件读取数据启动的,那么是怎么来启动这个链的呢?接下来看下这部分的启动,
首先是standardEngine类中的启动了。
// Standard container startup
super.start();
那么看下父类中的启动代码了,即CantainerBase中start()如下:
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}
根据上面的代码addChild和这里的 findChildren(),维护了一个链。这样就可以按照配置文件的不同配置,来启动加载了。
同时,我们可以看到的是责任链的整个部分都实现了观察者的Lifecycle接口,从而它们都是在观察者模式中处于主题对象的角色。观察者对象对其作相应的处理,启动前,启动,启动后,观察者会有不同的处理。在stop()中有关闭的处理,这里看下启动部分start()中观察者处理代码,。
//start中的部分代码
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
started = true;
//省略部分代码
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
// Start our thread
threadStart();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
分享到:
相关推荐
【标签】"tomcat源码分析"表明整个资料集专注于Tomcat的源代码级探索,适合于开发者或运维人员深入了解服务器的底层实现。 【文件名称列表】中的每个文档都对应一个特定主题: 1. "Tomcat处理HTTP请求源码分析.doc...
《Tomcat6源码分析——深入理解Web服务器的运行机制》 Tomcat6作为Apache软件基金会的Jakarta项目的一部分,是一款广泛使用的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为开发和部署...
### Tomcat架构的源码分析 #### 一、Tomcat的架构概述 Tomcat作为一款广泛使用的开源Java Servlet容器,其内部架构设计简洁而高效。本文档将对Tomcat的架构进行详细介绍,并从源码层面深入分析其核心组成部分。...
Tomcat源码剖析 : 整体架构 层层分析 源码解析 架构分析 (Http服务器功能:Socket通信(TCP/IP)、解析Http报文 Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑...
【TOMCAT源码分析(启动框架)】 Tomcat是一款广泛应用的开源Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为Web应用程序提供了运行环境。本篇文章将深入探讨Tomcat的系统框架及其启动流程...
tomcat的基础脚本分析 tomcat的源码启动分析 tomcat的web应用启动分析 tomcat的socket分析 tomcat的cocket与容器对接时序分析
Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...
【标题】"Tomcat源码分析" 在深入探讨Tomcat源码之前,首先需要了解Tomcat是什么。Tomcat是一款开源的、基于Java的Web应用服务器,由Apache软件基金会开发。它实现了Java Servlet和JavaServer Pages(JSP)规范,...
对 NIO 模式,请求的流程描述的很详细。值得去仔细的研究。
《Tomcat源码分析1——服务启动与架构详解》 Tomcat,作为一款广泛应用的开源Java Servlet容器,其内部架构和启动流程对于深入理解和优化Web应用程序至关重要。本文将重点解析Tomcat启动时的关键步骤和核心组件,...
《深入理解Tomcat源码分析1:Connector配置详解》 Tomcat,作为广泛使用的Java Servlet容器,其核心组件之一就是Connector,它负责处理Web服务器与客户端之间的通信。本篇文章将详细探讨Tomcat Connector的种类、...
3. **Apache Commons**:Apache Commons是Apache软件基金会的一个项目,提供了大量的Java实用工具类,Tomcat源码中可能使用了如Commons Logging、Commons Lang、Commons IO等模块。 4. **Servlet API**:Tomcat作为...
Apache Tomcat 8.5.23 源码分析 Apache Tomcat 是一个开源的、免费的Web服务器和Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是开发和部署Java Web应用的重要平台。深入理解Tomcat的源码有助...