- 浏览: 27736 次
- 性别:
- 来自: 广州
最新评论
这篇文章要弄懂一个问题,我们知道,一个链接器是跟一个容器关联的,容器跟链接器是在什么时候关联上的?
在明白这个问题前要先了解一下Digester库,这个库简单的说就是解析xml文件,这里有两个概念:模式和规则,所谓模式就是一个xml的标签,规则就是遇到一个xml标签需要做什么,看一下他主要的三个方法:
1:addObjectCreate(String pattern, String className, String attributeName) 根据模式pattern实例化一个对象className
2:addSetProperties(String pattern) 设置这个模式的属性
3:addSetNext(String pattern, String methodName, String paramType) 添加模式之间的关系,调用父模式的
上面可能不好理解,看tomcat是怎么用到Digester的,在org.apache.catalina.startup.Catalina.createStartDigester()的方法里(这个方法是在服务组件启动的时候调用的,详细参考Tomcat源码分析(一)--服务启动),在这个方法里有使用Digester来解析server.xml文件:
digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className");// 添加一个模式“Server/Service”,当在xml文件(这里是server.xml)里遇到“Server”标签下的Service标签的时候,根据标签Service的属性“className”为类名实例化一个对象,默认类名是"org.apache.catalina.core.StandardServer" digester.addSetProperties("Server/Service"); //设置对象StandardService的属性,有些什么属性由xml里的Service标签指定 digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service");//调用Service标签的上一级标签Server的对象(即StandardServer)的addService方法,把Service添加进Server,设置它们的关系,最后一个参数表示addService方法的参数类型
这样StandardServer和StandardService便有了所属关系,现在看容器跟链接器是怎么连接的,再看createStartDigester方法:
digester.addObjectCreate("Server/Service/Connector", "org.apache.catalina.connector.http.HttpConnector", "className"); digester.addSetProperties("Server/Service/Connector"); digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.Connector");
这里很好理解,跟上面的是一样的,遇到标签Server/Service/Connector的时候(这里简化了说法,应该是标签Server下的子标签Service的子标签Connector,有点拗口),实例化HttpConnector,然后在它的上一级父容器StandardService下调用addConnector,这样就把链接器HttpConnector添加进容器StandardService下了,看StandardService的addConnector方法:
public void addConnector(Connector connector) { synchronized (connectors) { connector.setContainer(this.container); //本来这里就应该把容器和连接器关联上的,但是在一开始tomcat启动的时候,Digester是先添加链接器,所以容器container还是为null的,但是没有关系,后面还会另一个地方关联他们,这里应该牢记的是容器和连接器都是在Service里面 connector.setService(this); Connector results[] = new Connector[connectors.length + 1]; System.arraycopy(connectors, 0, results, 0, connectors.length); results[connectors.length] = connector; connectors = results; if (initialized) { try { connector.initialize(); } catch (LifecycleException e) { e.printStackTrace(System.err); } } if (started && (connector instanceof Lifecycle)) { try { ((Lifecycle) connector).start(); } catch (LifecycleException e) { ; } } // Report this property change to interested listeners support.firePropertyChange("connector", null, connector); } }
这个方法很简单,就是把一个链接器connector添加到StandardService的connectors数组里,然后关联上StandardService的容器。代码上也做了一点说明(很重要)。连接器添加进StandardService了,现在看容器是什么时候添加进StandardService的,其实方法是一样的,再回到createStartDigester方法:
digester.addRuleSet(new EngineRuleSet("Server/Service/"));//这句代码是在createStartDigester方法里面 --------------------------》下面进入EngineRuleSet类的addRuleInstances方法 public void addRuleInstances(Digester digester) { digester.addObjectCreate(prefix + "Engine", "org.apache.catalina.core.StandardEngine", "className"); digester.addSetProperties(prefix + "Engine"); digester.addRule(prefix + "Engine", new LifecycleListenerRule (digester, "org.apache.catalina.startup.EngineConfig", "engineConfigClass")); digester.addSetNext(prefix + "Engine", "setContainer", "org.apache.catalina.Container"); //这里调用StandardService的方法setContainer方法,把容器添加进StandardService里面 }
先不去纠结Digester是怎么进入addRuleInstances方法的,当我们调用了digester.addRuleSet(new EngineRuleSet("Server/Service/"));方法,Digester便会自动调用到EngineRuleSet类的addRuleInstances方法,在方法里面无非也是添加各种模式和规则,根据上面的添加规则,很容易知道这里又添加了一个StandardEngine对象(容器),然后又在该模式的上一级模式Server/Service添加StandardEngine跟StandardService的关系,即通过setContainer方法把容器添加进StandardService里。以下是StandardService的setContainer方法:
public void setContainer(Container container) { Container oldContainer = this.container; if ((oldContainer != null) && (oldContainer instanceof Engine)) ((Engine) oldContainer).setService(null); this.container = container; if ((this.container != null) && (this.container instanceof Engine)) ((Engine) this.container).setService(this); if (started && (this.container != null) && (this.container instanceof Lifecycle)) { try { ((Lifecycle) this.container).start(); } catch (LifecycleException e) { ; } } //重点!!!!!!!! synchronized (connectors) { //下面是把StandardService下的所有连接器都关联上StandardService下的容器,这样连接器就跟容器关联上了。 for (int i = 0; i < connectors.length; i++) connectors[i].setContainer(this.container); } if (started && (oldContainer != null) && (oldContainer instanceof Lifecycle)) { try { ((Lifecycle) oldContainer).stop(); } catch (LifecycleException e) { ; } } // Report this property change to interested listeners support.firePropertyChange("container", oldContainer, this.container); }
上面的代码做了各种判断,然后把容器设置到StandardService下,在“同步代码块”处,把容器和链接器关联上了,至此,容器和链接器就关联上了。回过头想想,其实很简单,就是用Digester根据设定的模式读取server.xml,然后调用了两个关键的方法setContainer和addConnector,就把容器和链接器关联上了。关联上了就可以明白在Tomcat源码分析(二)--连接处理一文的最后process方法里代码:connector.getContainer().invoke(request,response);的含义了。下篇希望说明白调用invoke之后发生的一切。
发表评论
-
Tomcat源码分析(一)--服务启动
2012-07-05 11:11 454对Tomcat感兴趣是由 ... -
Tomcat源码分析(二)--连接处理
2012-07-06 08:35 411目标:在这篇文章希望搞明白http请求到tomcat后是 ... -
Tomcat源码分析(四)--容器处理链接之责任链模式
2012-07-07 16:21 391目标:在这篇文章希望搞明白connector.getCont ... -
Tomcat源码分析(五)--容器处理连接之servlet的映射
2012-07-08 09:32 432本文所要解决的问题:一个http请求过来,容器是怎么知道选 ... -
Tomcat源码分析(六)--日志记录器和国际化
2012-07-09 08:34 530日志记录器挺简单的,没有很多东西,最主要的就是一个Lo ... -
Tomcat源码分析(七)--单一启动/关闭机制(生命周期)
2012-07-10 12:23 473在前面的大部分文章都是讲连接器和容器的,以后的内容会偏向写一 ... -
Tomcat源码分析(八)--载入器
2012-07-10 20:14 546在讲Tomcat的载入器之前,先要了解一下java的类加载 ... -
Tomcat源码分析(十)--部署器
2012-07-12 09:02 532我们知道,在Tomcat的世界里,一个Host容器代表一 ... -
Tomcat源码分析(九)--Session管理
2012-07-11 15:16 676在明白Tomcat的Session机 ...
相关推荐
6. **src**:这是最重要的部分,包含了Tomcat所有核心模块的源代码,如Catalina(核心Servlet容器)、 Coyote(HTTP/HTTPS连接器)、Jasper(JSP编译器)等。 7. **common`, `server`, `shared`:这些是类库目录,...
### Tomcat源码分析 #### 一、概述 Apache Tomcat是Java开发人员最常用的Web服务器之一,它不仅能够作为独立的应用程序运行Servlet和JavaServer Pages(JSP),还可以作为一个内嵌的容器来运行Web应用。Tomcat的...
1. **连接器接收请求**:`Connector`组件负责监听客户端请求,并将请求传递给适配器。 2. **协议适配器处理请求**:适配器(如`CoyoteAdapter`)将请求解析为内部格式,并调用`ProtocolHandler`处理请求。 3. **容器...
在深入研究源码时,建议先了解Servlet和JSP的基本概念,以及Tomcat的核心组件,如Catalina(核心引擎)、 Coyote(HTTP连接器)和 Jasper(JSP编译器)。这将帮助你更好地理解源码中的类和方法的作用。 此外,...
通过研究Tomcat源码,开发者可以学习到如何构建一个高性能的Servlet容器,掌握Java Web应用的核心运行机制,这对于提升Java EE开发能力大有裨益。同时,如果你遇到Tomcat的使用问题或者想要进行定制化开发,源码分析...
9. **源码分析**:书中提供的源码可以帮助开发者了解Tomcat如何处理请求、调度线程、管理会话等。例如,你可以看到`org.apache.catalina.connector.Request`类如何解析请求,`org.apache.catalina.Container`如何...
综上,掌握Tomcat并发处理的知识,结合源码分析和工具应用,能有效地提升服务器的并发处理能力,应对高流量网站的需求。这份"Tomcat并发资料.txt"文件可能包含上述部分或全部知识点的详细解释,是学习和优化Tomcat...
对于源码和工具相关的标签,这意味着我们可能涉及到Tomcat的源代码分析,以及如何使用Eclipse作为开发工具来理解和调试Tomcat。开发者可以通过阅读和修改Tomcat源代码来学习其内部工作原理,提高对Java Web开发的...
Tomcat的核心组件包括Connector(连接器)和Container(容器)。Connector负责与客户端进行通信,接收HTTP请求并返回响应,而Container则负责处理请求,执行Servlet代码,并生成响应。两者结合在Service中,Service...
**源码分析** StandardService的`setContainer`和`addConnector`方法展示了如何配置和管理Service的组件。当添加或更改Container时,需要确保与Service正确关联,并可能启动或停止相关的生命周期。同样,添加...
【Java项目实战-物流信息网的设计与实现】是一个基于Java技术的综合项目,旨在提供一个高效、实用的物流信息管理平台。该项目涵盖了软件开发的多个关键环节,包括需求分析、系统设计、数据库构建、编码实现以及部署...
Struts2的动作配置文件(struts.xml)定义了动作映射,关联URL路径到特定的Action类,还可能包含拦截器,用于实现如日志、权限检查等附加功能。 开发步骤可能包括以下内容: 1. **创建项目**:在MyEclipse中新建一...
这是一个关于使用SSM(Spring、SpringMVC、MyBatis)框架和微信小程序开发的会议发布与预约系统的毕业设计项目。这个系统旨在提供一个便捷的平台,让用户能够方便地查看会议信息、预约会议以及进行相关的管理操作。...
蜗牛兼职网是一个基于SpringBoot框架的项目,用于搭建一个在线兼职信息发布的平台。...通过对源码的分析和研究,开发者可以深入了解SpringBoot如何与SSM、JSP等技术配合,以及如何构建一个完整的Web应用。
这是一个基于Java和MySQL的学生学籍后台管理系统源码项目。该项目主要涵盖了Java编程语言与MySQL数据库在开发管理信息系统方面的应用,适合初学者学习和理解MVC(Model-View-Controller)架构以及数据库操作。 1. *...
Servlet是Java Web开发中的核心组件,它是一种...结合源码分析和适当的工具,如调试器和日志记录,可以更好地理解和优化Servlet的性能。在实际项目中,熟练运用Servlet能帮助开发者构建出功能强大、扩展性强的Web应用。
当客户机第一次调用一个Stateful Session Bean 时,容器必须立即在服务器中创建一个新的Bean实例,并关联到客户机上,以后此客户机调用Stateful Session Bean 的方法时容器会把调用分派到与此客户机相关联的Bean实例...
10. **部署与测试**:项目完成后,需要在服务器上进行部署,可能使用Tomcat或Jetty等Servlet容器。同时,进行单元测试和集成测试,确保每个功能都能正常工作,例如使用JUnit进行后端测试,使用Selenium进行前端功能...
- 嵌入式服务器:支持嵌入Tomcat、Jetty等Web容器。 - 易于使用的依赖启动器:提供了一些约定好的依赖管理方式。 - 独立的应用程序:可以被打包成jar或war格式,方便部署。 2. **Vue.js** - **简介**:Vue.js是...