- 浏览: 842473 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
renzhengzhi:
请教一下楼主,公有云和私有云的开发,具体要做哪些工作呢?我拿到 ...
4,云的4 种模式 -
SangBillLee:
我用了solr5.5,用SolrQuery查询,没法高亮,不知 ...
solr5.x快速入门 -
lw900925:
这翻译读起来真是别扭。
solr in action翻译-第一章1.1 -
springjpa_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
Spring MVC性能提升 -
h416373073:
正遇到了此问题不知如何解决, 多谢分享
solr错误
Wrapper接口在Catalina中的标准实现StandardWrapper类的详细实现过程。
一共有四种容器:engine(引擎),host(主机),context(上下文)和wrapper(包装器)
一个上下文一般包括一个或者多个包装器,每一个包装器表示一个servlet
方法调用序列Sequence of Methods Invocation
对于每一个连接,连接器都会调用关联容器的invoke方法。接下来容器调用它的所有子容器的invoke方法
如果一个连接器跟一个StadardContext实例相关联,那么连接器会调用StandardContext实例的invoke方法,
该方法会调用所有它的子容器的invoke方法
过程
1,连接器创建请求和响应对象
2,连接器调用StandardContext的invoke方法
3,StandardContext的invoke方法必须调用该上下文容器的流水线的invoke方法,
所以StandardContext的流水线会调用StandardContextValve的invoke方法
4,StandardContextValve的invoke方法得到合适的包装器来对请求进行服务并调用包装器的invoke方法
5,StandardWrapper是包装器的标准实现,StandardWrapper对象的invoke方法调用流水线的invoke方法。
6,StandardWrapper流水线的基本阀门时StandardWrapperValve。因此StandardWrapperValve的invoke方法会被调用。
StandardWrapperValve的invoke方法会调用包装器的allocate方法获得一个servlet的实例。
7,当一个servlet需要被加载的时候,方法allocate调用方法load来加载一个servlet
8,方法load会调用servlet的init方法
我们主要关注的是一个servlet被调用的时候发生的细节。因此我们需要自习看StandardWrapper和StandarWrapperValve类
javax.servlet.SingleThreadModel
一个servlet可以实现javax.servlet.SingleThreadModel接口,实现此接口的一个servlet通俗称为SingleThreadModel(STM)的程序组件。
根据Servlet规范,实现此接口的目的是保证servlet一次只能有一个请求。
StandardWrapper
一个StandardWrapper对象的主要职责是:加载它表示的servlet并分配它的一个实例。该StandardWrapper不会调用servlet的service方法
这个任务留给StandardWrapperValve对象,在StandardWrapper实例的基本阀门管道。
StandardWrapperValve对象通过调用StandardWrapper的allocate方法获得Servlet实例。
在获得Servlet实例之后的StandardWrapperValve调用servlet的service方法
在servlet第一次被请求的时候,StandardWrapper加载servlet类。它是动态的加载servlet,所以需要知道servlet类的完全限定名称。
通过StandardWrapper类的setServletClass方法将servlet的类名传递给StandardWrapper。
必须考虑一个servlet是否实现了SingleThreadModel接口。 如果一个servlet没有实现SingleThreadModel接口,
StandardWrapper加载该servlet一次,对于以后的请求返回相同的实例即可。
对于一个STM servlet,情况就有所不同了。StandardWrapper必须保证不能同时有两个线程提交STM servlet的service方法。
Servlet instance = <get an instance of the servlet>; if ((servlet implementing SingleThreadModel>) { synchronized (instance) { instance.service(request, response); } }else{ instance.service(request, response); }
Allocating the Servlet
StandardWrapperValve的invoke方法调用了包装器的allocate方法来获得一个请求servlet的实例
因此StandardWrapper类必须实现该接口
public javax.servlet.Servlet allocate() throws ServletException;
由于要支持STM servlet,这使得该方法更复杂了一点。实际上,该方法有两部分组成,
一部分负责非STM servlet的工作,另一部分负责STM servlet。
第一部分的结构如下
if (!singleThreadModel) {
// returns a non-STM servlet instance
}
布尔变量singleThreadModel负责标志一个servlet是否是STM servlet。
它的初始值是false,loadServlet方法会检测加载的servlet是否是STM的,如果是则将它的值该为true
第二部分处理singleThreadModel为true的情况
synchronized (instancepool) {
// returns an instance of the servlet from the pool
}
对于非STM servlet,StandardWrapper定义一个java.servlet.Servlet类型的实例
private Servlet instance = null;
方法allocate检查该实例是否为null,如果是调用loadServlet方法来加载servlet。然后增加contAllocated整型并返回该实例。
if (!singleThreadModel) { if (instance == null) { synchronized (this) { if (instance == null) { try { instance = loadServlet(); }catch (ServletException e) { throw e; } } } } if (!singleThreadModel) { countAllocated++; return (instance); }
Loading the Servlet
StandardWrapper实现了Wrapper接口的load方法,load方法调用loadServlet方法来加载一个servlet类,
并调用该servlet的init方法,传递一个javax.servlet.ServletConfig实例
方法loadServlet首先检查StandardWrapper是否表示一个STM servlet。
如果不是并且该实例不是null(即以前已经加载过),直接返回该实例:
if (!singleThreadModel && (instance != null))
return instance;
如果该实例是null或者是一个STM servlet,继续该方法的其它部分
ServletConfig对象
StandardWrapper的loadServlet方法在加载了loaded方法之后调用的发送者的init方法
init方法传递一个javax.servlet.ServletConfig实例
StandardWrapper实现javax.servlet.ServletConfig接口和Wrapper接口。
ServletConfig接口有以下四个方法getServletContext, getServletName, getInitParameter, 和getInitParameterNames
getServletContext
public ServletContext getServletContext()
一个StandardWrapper实例必须是一个StandardContext容器的子容器。也就是说,StandardWrapper的父容器是StandardContext
StandardWrapper中方法getServletContext的实现
public ServletContext getServletContext() { if (parent == null) return (null); else if (!(parent instanceof Context)) return (null); else return (((Context) parent).getServletContext()); }
现在你知道不能单独部署一个包装器来表示一个Servlet,包装器必须从属于一个上下文容器,
这样才能使用ServletConfig对象使用getServletContext方法获得一个ServletContext实例。
getServletName
该方法返回Servlet的名字
public java.lang.String getServletName()
getServletName方法在StandardWrapper类中实现
public String getServletName() {
return (getName());
}
它简单的调用StandardWrapper 的父类ContainerBase类的getName方法
在ContainerBase中如下实现
public String getName() {
return (name);
}
使用setName方法来设置name的值。回忆是如何调用StandardWrapper实例的setName方法来传递Servlet的name的
getInitParameter
该方法返回指定参数的值
public java.lang.String getInitParameter(java.lang.String name)
在StandardWrapper中,初始化参数被存放在一个名为parameters的HashMap中
private HashMap parameters = new HashMap(); StandardWrapper类的addInitParameter方法来填充parameters。传递参数的名字和值。 public void addInitParameter(String name, String value) { synchronized (parameters) { parameters.put(name, value); } fireContainerEvent("addInitParameter", name); } StandardWrapper对getInitParameter的实现: public String getInitParameter(String name) { return (findInitParameter(name)); }
getInitParameterNames
该方法返回所有初始化参数名字的枚举(Enumeration),
public java.util.Enumeration getInitParameterNames()
StandardWrapper类中getInitParameterNames的实现:
public Enumeration getInitParameterNames() {
synchronized (parameters) {
return (new Enumerator(parameters.keyset()));
}
}
Parent and Children
一个包装器表示一个独立Servlet的容器。这样,包装器就不能再有子容器,因此不可以调用它的addChild方法,
如果调用了会得到一个java.langIllegalStateException
一个包装器的父容器只能是一个上下文容器。如果传递的参数不是一个上下文容器,
它的setParent方法会抛出java.lang.IllegalArgumentException
public void setParent(Container container) { if ((container != null) && !(container instanceof Context)) throw new IllegalArgumentException ( sm.getString("standardWrapper.notContext")); super.setParent(container); }
StandardWrapperFacade
StandardWrapper调用它价值的Servlet的init方法。该方法需要一个javax.servlet.ServletConfig的参数,
而StandardWrapper类自己就实现了ServletConfig接口。所以,理论上StandardWrapper可以将它自己作为参数传递给init方法。
但是StandardWrapper需要对Servlet隐藏他的大多数public方法。
为了实现这一点,StandardWraper将它自己包装的一个StandardWrapperFacade实例中
StandardWrapperValve
StandardWrapperValve是StandardWrapper实例上的基本阀门,主要工作是
1,提交Servlet的所有相关过滤器
2,调用发送者的service方法
要实现这些内容,下面是StandardWrapperValve在他的invoke方法要实现的
· 调用StandardWrapper的allocate的方法来获得一个servlet实例
· 调用它的private createFilterChain方法获得过滤链
· 调用过滤器链的doFilter方法。包括调用servlet的service方法
· 释放过滤器链
· 调用包装器的deallocate方法
· 如果Servlet无法使用了,调用包装器的unload方法
接下来是invoke方法
try { if (!unavailable) { servlet = wrapper.allocate(); } } ......... try { response.sendAcknowledgement(); } ........ ApplicationFilterChain filterChain = createFilterChain(request, servlet); try { String jspFile = wrapper.getJspFile(); if (jspFile != null) sreq.setAttribute(Globals.JSP_FILE_ATTR, jspFile); else sreq.removeAttribute(Globals.JSP_FILE_ATTR); if ((servlet != null) && (filterChain != null)) { filterChain.doFilter(sreq, sres); } sreq.removeAttribute(Globals.JSP_FILE_ATTR); .... } ........... try { if (filterChain != null) filterChain.release(); } ... try { if (servlet != null) { wrapper.deallocate(servlet); } } ........ try { if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) { wrapper.unload(); } }
最重要的方法是createFilterChain方法并调用过滤器链的doFilter方法。
方法createFilterChain创建了一个ApplicationFilterChain实例,并将所有的过滤器添加到上面
FilterDef
org.apache.catalina.deploy.FilterDef表示一个过滤器定义,就像是在部署文件中定义一个过滤器元素那样
public final class FilterDef { /** * The description of this filter. */ private String description = null; private String displayName = null; private String filterClass = null; private String filterName = null; private String largeIcon = null; private String smallIcon = null; private Map parameters = new HashMap(); public String toString() { StringBuffer sb = new StringBuffer("FilterDef["); sb.append("filterName="); sb.append(this.filterName); sb.append(", filterClass="); sb.append(this.filterClass); sb.append("]"); return (sb.toString()); } public void addInitParameter(String name, String value) { parameters.put(name, value); } }
FilterDef类中的每一个属性都代表一个可以在过滤器中出现的子元素。该类包括一个Map类型的变量表示一个包含所有初始参数的Map。
方法addInitParameer添加一个name/value对到该Map。
ApplicationFilterConfig
ApplicationFilterConfig实现了javax.servlet.FilterConfig接口。
ApplicationFilterConfig负责管理web应用程序启动的时候创建的过滤器实例。
传递一个org.apache.catalina.Context对象和FilterDef对象给ApplicationFilterConfig的构造来创建一个ApplicationFilterConfig实例:
public ApplicationFilterConfig(Context context, FilterDef filterDef)
throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException
Context对象表示一个一个web应用而FilterDef表示一个过滤器定义。
Filter getFilter() throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException { if (this.filter != null) return (this.filter); String filterClass = filterDef.getFilterClass(); ClassLoader classLoader = null; if (filterClass.startsWith("org.apache.catalina.")) classLoader = this.getClass().getClassLoader(); else classLoader = context.getLoader().getClassLoader(); ClassLoader oldCtxClassLoader = Thread.currentthread().getContextClassLoader(); Class clazz = classLoader.loadClass(filterClass); this.filter = (Filter) clazz.newInstance(); filter.init(this); return (this.filter); }
ApplicationFilterChain
ApplicationFilterChain类是实现了javax.servlet.FilterChain接口。
StandardWrapperValve类中的invoke方法创建一个该类的实例并且调用它的doFilter方法。
ApplicationFilterChain类的doFilter的调用该链中第一个过滤器的doFilter方法。
Filter接口中doFilter方法的签名如下:
public void doFilter(ServletRaquest request, ServletResponse response, FilterChain chain)
在他的doFilter方法中,一个过滤器可以调用另一个过滤器链的doFilter来唤醒另一个过来出去
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // do something here ... chain.doFilter(request, response); }
在doFilter方法最好一行,它调用过滤链的doFilter方法。如果该过滤器是过滤链的最后一个过滤器,
它叫调用请求的Servlet的service方法。如果过滤器没有调用chain.doFilter,下一个过滤器就不会被调用。
发表评论
-
21,tomcat关闭钩子
2012-11-22 20:35 6646在很多环境下,在关闭应用程序的时候需要做一些清理工作。问题在于 ... -
20,tomcat的XML解析---digester
2012-11-22 20:07 1559tomcat使用server.xml配置属性信息Tomcat使 ... -
19tomcat的服务器和服务
2012-11-20 20:10 1077Server服务器 Server接口表示整个Catalina ... -
18,tomcat的主机(host)和引擎
2012-11-16 09:13 2351如果需要在一个Tomcat部署中部署多个上下文,需要使用一个主 ... -
附,listener、 filter、servlet 加载顺序及其详解
2012-11-15 09:10 985一、 1、启动一个WEB项 ... -
17,tomcat中StandardContext
2012-11-15 08:59 5043一个上下文容器(Context)代表一个web应用,每一个上下 ... -
15,tomcat安全
2012-11-14 09:02 1201有些web应用程序的内容是有限制的,只允许有权限的用户在提供正 ... -
14,tomcat session管理
2012-11-14 09:01 1104Catalina通过一个叫管理器的组建来完成Session的管 ... -
13.tomcat加载器
2012-11-13 13:21 1376库(repository)和源(res ... -
12,tomcat日志处理
2012-11-13 13:15 1248日志系统是一个记录信息的组件。在Catalina中,日志系统是 ... -
附:JAVA事件处理--观察者模式
2012-11-12 10:33 1001简单地说,观察者模式 ... -
11.tomcat生命周期
2012-11-12 10:26 988Catalina由多个组件组成,当Catalina启动的 ... -
10.容器
2012-11-12 10:12 1351容器是一个处理用户servlet请求并返回对象给we ... -
9.Tomcat的默认连接器
2012-11-12 08:52 1179Tomcat连接器是一个可以插入servlet容器的独立模块, ... -
8.连接器
2012-11-12 08:46 939一个可以创建更好的请 ... -
7,Facade外观模式
2012-11-08 11:28 950外观模式:为子系统中的一组接口提供了一个一致的界面,此模式定义 ... -
6,一个简单的servlet容器
2012-11-08 11:10 855总的来说,一个全功能的servlet容器会为servlet的每 ... -
5.javax.servlet.Servlet接口
2012-11-08 09:18 951javax.servlet.Servlet接口Servlet编 ... -
4,一个简单的tomcat
2012-11-07 18:10 946流程图如下 -
3.ServerSocket 与 Socket的区别
2012-11-07 16:56 11871.1 ServerSocket类创建 ...
相关推荐
**WEB服务器工作机制由浅至深:Tomcat StandardWrapper翻译分析** 在深入理解Web服务器的工作机制时,Tomcat作为Apache组织的开源Java Servlet容器,扮演着关键角色。本篇将聚焦于Tomcat的内部组件——...
StandardContext是Tomcat中的上下文实现, StandardWrapper是Tomcat中的Wrapper实现。 在StandardHost的启动过程中,首先会初始化startStopExecutor线程池,然后启动所有的子容器,包括StandardContext和...
- **工厂模式**:Tomcat使用工厂模式创建Servlet实例,如StandardWrapper类中的createServlet方法。 - **责任链模式**:请求在不同级别的Container之间传递,每个Container都有机会处理请求,直到找到合适的...
Tomcat源码中实现了Servlet的生命周期管理,包括加载、初始化、服务、销毁等阶段。`org.apache.catalina.core.StandardWrapper`类负责管理单个Servlet实例的生命周期。 3. **请求处理**: `org.apache.coyote`包...
通过对Tomcat 8.0源码的学习,开发者能够更深入地理解Web服务器的工作机制,从而更好地优化应用性能,解决复杂问题,甚至参与到Tomcat的贡献和维护中。这是一条通往Java Web高级开发者之路的必经之路。
在`org.apache.catalina.core.StandardWrapper`类中,可以看到这些过程的详细实现。 5. **安全性与权限控制** Tomcat提供了基于角色的访问控制(RBAC),以及SSL/TLS支持来增强安全性。`conf/tomcat-users.xml`...
8. **内存泄漏防护**:Tomcat 7包含了一些防止内存泄漏的机制,比如在`Context`销毁时清理静态变量,以及在`StandardWrapper`中跟踪未关闭的`ServletOutputStream`和`ServletInputStream`。 9. **更好的日志系统**...
Catalina是Tomcat的核心组件,负责处理Servlet和JSP的请求,而`tomcat-catalina-7.0.27.jar`则是Catalina模块在Tomcat 7.0.27版本中的实现文件。 1. **Catalina架构** Catalina遵循Java Servlet规范,提供了一个...
《深入剖析Tomcat》从最基本的HTTP请求开始,直至使用JMX技术管理Tomcat中的应用程序,逐一剖析Tomcat的基本功能模块,并配以示例代码,使读者可以逐步实现自己的Web服务器。 目录 第1章 一个简单的web服务器 1.1...
【标题】"Tomcat 8源代码 Servlet源代码" 涉及到的是Apache Tomcat服务器的源码分析,特别是Servlet容器的相关实现。Tomcat是一个开源的轻量级Web应用服务器,广泛用于部署Java Servlet和JavaServer Pages (JSP)应用...
5. **部署与加载**:`StandardContext`和`StandardWrapper`是容器的实现,它们负责加载和管理Web应用及其Servlet。`WEB-INF/web.xml`是应用的部署描述符,定义了应用的结构和行为。 6. **安全性**:Tomcat的安全性...
在Tomcat中,`org.apache.catalina.core.StandardWrapper`类扮演了ServletConfig的角色,存储了Servlet的配置信息。 4. **Request与Response处理** 当请求到达Tomcat时,会通过`org.apache.coyote.Request`对象...
通过对Tomcat请求处理流程中各个组件的解析,我们可以更深入地理解Tomcat的工作原理。这种基于UML序列图的描述方式不仅能够清晰地展现各个组件之间的交互关系,还能够帮助开发者更好地理解Tomcat的架构设计思想。这...
Tomcat6是Tomcat系列中的一个稳定版本,广泛应用于各种规模的应用开发中。 ##### 架构组成: 1. **Connector**:负责接收客户端请求并将它们分发到相应的处理组件。 2. **Container**:主要负责管理应用程序生命...
- **StandardWrapper**: 实现了Wrapper接口,用于管理Servlet实例。 通过阅读这些类的实现,可以更深入地理解Tomcat的工作机制和技术细节。 #### 六、总结 本文介绍了Tomcat的基本概念、工作原理、架构设计、容器...
`StandardWrapper`实现了`Wrapper`接口,每个Servlet实例都有一个对应的`Wrapper`对象,用于管理Servlet的生命周期。 **5. 安全性** Tomcat的安全性体现在多个层面,如`Realm`接口及其实现,如`MemoryRealm`和`...
7. **线程模型**:Tomcat采用多线程模型处理请求,`Executor`接口及其实现允许自定义线程池,以优化并发性能。 8. **连接器与协议处理器**:Tomcat支持多种连接器,如基于NIO的` CoyoteNioProtocol`,基于APR的`...
在Tomcat7版本中,Catalina是核心组件之一,负责处理HTTP请求和响应,实现了Servlet和JSP规范。本篇文章将对Catalina包的源码进行深度剖析,帮助读者理解其内部工作机制。 首先,我们来看Catalina的核心架构。...
Apache Tomcat是一款开源的Java Servlet容器,它实现了Java EE中的Web应用服务器规范,特别是Servlet和JSP标准。源代码分析是深入理解Tomcat工作原理、性能优化和自定义配置的关键。下面将对Tomcat源码进行详细的...