- 浏览: 839736 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
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错误
一个上下文容器(Context)代表一个web应用,每一个上下文包括多个包装器(Wrapper),每个包装器代表一个Servlet
上下文还需要其它的一些组件如加载器和管理器
Context接口的标准实现,org.apache.catalina.core.StandardContext类
StandardContext配置
创建一个StandardContext实例之后,必须调用它的start方法,这样它就能为受到的HTTP请求服务了。一个StandardContext对象可能启动失败,
这时候属性available被设置为false,属性available表示了StandardContext对象的可用性。
在一个Tomcat部署中,StandardContext的配置过程做了以下事情:准备读取和解析%CATALINA_HOME%/conf 目录下面的web.xml,
部署所有应用程序,确保StandardContext实例可以处理应用级别的web.xml。
另外,配置需要添加一个验证器阀门和证书阀门(authenticator valve and a certificate valve)
StandardContext的属性之一是它属性configured,用来表示该StandardContext是否已经配置了
StandardContext使用一个事件监听器来作为它的配置器
当StandardContext实例的start方法被调用的时候,首先触发一个生命周期事件
。该事件唤醒一个监听器来配置该StandardContext实例。配置成功后,该监听器将configured属性设置为true。
否则,StandardContext对象拒绝启动,这样就不能对HTTP请求进行服务了。
StandardContext构造函数
public StandardContext() {
super();
pipeline.setBasic(new StandardContextValve());
namingResources.setContainer(this);
}
在构造函数中,最重要的事情是在StandardContext的流水线上添加了一个类型为StandardContextValve的基本阀门
启动StandardContext
Start方法初始化StandardContext对象并让生命周期监听器配置该StandardContext实例。如果配置成功,
生命周期监听器会将configured属性设置为true。最后start方法,将available属性设置为true或者false。
如果是true的话表示该StandardContext属性配置完毕并且所有相关子容器和组件已经成功启动,
这样就能对HTTP请求进行服务了,如果是false则表示出现了错误。
public synchronized void start() throws LifecycleException { if (started) throw new LifecycleException (sm.getString("containerBase.alreadyStarted", logName())); lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); setAvailable(false); setConfigured(false); boolean ok = true; if (getResources() == null) { try { if ((docBase != null) && (docBase.endsWith(".war"))) setResources(new WARDirContext()); else setResources(new FileDirContext()); }catch (IllegalArgumentException e) { ok = false; } } if (ok && (resources instanceof ProxyDirContext)) { DirContext dirContext = ((ProxyDirContext) resources).getDirContext(); if ((dirContext != null) && (dirContext instanceof BaseDirContext)) { ((BaseDirContext) dirContext).setDocBase(getBasePath()); ((BaseDirContext) dirContext).allocate(); } } if (getLoader() == null) { if (getPrivileged()) { setLoader(new WebappLoader(this.getClass().getClassLoader())); }else{ setLoader(new WebappLoader(getParentClassLoader())); } } if (getManager() == null) { setManager(new StandardManager()); } // Initialize character set mapper getCharsetMapper(); // Post work directory postWorkDirectory(); String useNamingProperty = System.getProperty("catalina.useNaming"); if ((useNamingProperty != null) && (useNamingProperty.equals("false"))) { useNaming = false; } if (ok && isUseNaming()) { if (namingContextListener == null) { namingContextListener = new NamingContextListener(); namingContextListener.setDebug(getDebug()); namingContextListener.setName(getNamingContextName()); addLifecycleListener(namingContextListener); } } ClassLoader oldCCL = bindThread(); if (ok) { try { addDefaultMapper(this.mapperClass); started = true; if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); if ((logger != null) && (logger instanceof Lifecycle)) ((Lifecycle) logger).start(); // Unbinding thread unbindThread(oldCCL); oldCCL = bindThread(); if ((cluster != null) && (cluster instanceof Lifecycle)) ((Lifecycle) cluster).start(); if ((realm != null) && (realm instanceof Lifecycle)) ((Lifecycle) realm).start(); if ((resources != null) && (resources instanceof Lifecycle)) ((Lifecycle) resources).start(); Mapper mappers[] = findMappers(); for (int i = 0; i < mappers.length; i++) { if (mappers[i] instanceof Lifecycle) ((Lifecycle) mappers[i]).start(); } Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null); if ((manager != null) && (manager instanceof Lifecycle)) ((Lifecycle) manager).start(); } finally { // Unbinding thread unbindThread(oldCCL); } } if (!getConfigured()) ok = false; if (ok) getServletContext().setAttribute (Globals.RESOURCES_ATTR, getResources()); if (ok) { postWelcomeFiles(); } if (ok) { if (!listenerStart()) ok = false; } if (ok) { if (!filterStart()) ok = false; } // Load and initialize all "load on startup" servlets if (ok) loadOnStartup(findChildren()); unbindThread(oldCCL); if (ok){ setAvailable(true); }else{ stop(); setAvailable(false); } lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); }
下面是该方法做的事情:
· 触发BEFORE_START事件
· 设置availability属性为false
· 设置configured属性为false
· 设置源(resources)
· 设置加载器
· 设置管理器
· 初始化属性map
· 启动跟该上下文相关的组件
· 启动子容器(包装器)
· 启动流水线
· 启动管理器
· 触发START事件
。监听器(ContextConfig)会进行一系列配置操作,配置成功后,将StandardContext实例的configured属性设置为true。
· 检查configured属性的值,如果为true:调用postWelcomPages方法,加载子包装器,并将available属性设置为true。
如果configured属性为false调用stop方法
· 触发AFTER_START事件
Invoke方法
StandardContext's方法由相关联的连接器调用,
如果该上下文是一个主机(host)的子容器,
有该主机的invoke方法调用。StandardContext的invoke方法首先检查是否正在重加载该应用程序,
是的话,等待知道加载完毕。然后调用它的父类ContainerBase的invoke方法
public void invoke(Request request, Response response){ while (getPaused()) { try { Thread.sleep(1000); } catch (InterruptedException e) { ; } } if (swallowOutput) { try { SystemLogHandler.startCapture(); super.invoke(request, response); } }else { super.invoke(request, response); } }
方法getPaused获得属性paused的值,当应用程序正在加载的时候该属性为ture。
StandardContextMapper
对于每一个请求,invoke方法都会调用StandarContext流水线基本阀门的invoke方法。
StandarContext的基本阀门用org.apache.catalina.core.StandardContextValve类表示。
StandardContextValve实例查找包含它的StandardContext。StandardContextValve使用上下文容器的map来查找合适的包装器
StandardContext的父类ContainerBase定义了addDefaultMapper方法来添加
protected void addDefaultMapper(String mapperClass) { if (mapperClass == null) return; if (mappers.size() >= 1) return; try { Class clazz = Class.forName(mapperClass); Mapper mapper = (Mapper) clazz.newInstance(); mapper.setProtocol("http"); addMapper(mapper); } catch (Exception e) {} }
重加载支持
StandardContext定义了reloadable属性来标识是否支持应用程序的重加载。
当允许重加载的时候,当web.xml或者WEB-INF/classes目录下的文件被改变的时候会重加载。
StandardContext 中Loader接口的标准实现WebappLoader类,有一个单独线程来检查WEB-INF目录下面所有类和JAR文件的时间戳
你需要做的是启动该线程,将 WebappLoader关联到StandardContext,使用setContainer方法即可
public void setContainer(Container container) { if ((this.container != null) && (this.container instanceof Context)) ((Context) this.container).removePropertyChangeListener(this); Container oldContainer = this.container; this.container = container; support.firePropertyChange("container", oldContainer, this.container); // Register with the new Container (if any) if ((this.container!=null) && (this.container instanceof Context)) { setReloadable( ((Context) this.container).getReloadable() ); ((Context) this.container).addPropertyChangeListener(this); } }
注意最后一个if语句块中,如果容器是一个上下文容器,调用setReloadable方法,
也就是说WebappLoader的reloadable属性跟StandardContext的reloadable属性相同。
下面是WebappLoader对setReload方法的实现:
public void setReloadable(boolean reloadable) { boolean oldReloadable = this.reloadable; this.reloadable = reloadable; support.firePropertyChange("reloadable", new Boolean(oldReloadable), new Boolean(this.reloadable)); if (!started) return; if (!oldReloadable && this.reloadable) threadStart(); else if (oldReloadable && !this.reloadable) threadStop(); } }
如果将reloadable属性设置为true,调用threadStart方法。如果从true到false,则调用threadStop方法。
threadStart方法启动一个线程持续的检查WEB-INF目录下面的类文件和JAR文件的时间戳。threadStop方法用于停止该线程。
类的时间戳是由backgroundProcess方法调用
backgroundProcess方法
一个上下文容器需要其它组件如加载器和管理器的支持。这些组件通常需要一个单独的线程来处理后台过程(background processing)
所有的后台过程都分享同一个线程。如果一个组件或者是容器需要定期的来执行操作,
它需要做的是将这些代码写入到backgroundProcess方法即可。
protected void threadStart() { if (thread != null) return; if (backgroundProcessorDelay <= 0) return; threadDone = false; String threadName = "ContainerBackgroundProcessor[" + toString() + "]"; thread = new Thread(new ContainerBackgroundProcessor(), threadName); thread.setDaemon(true); thread.start(); }
方法threadStart传递一个ContainerBackgroundProcessor对象创建一个新线程。
ContainerBackgroundProcessor实现了java.lang.Runnable接口
protected class ContainerBackgroundProcessor implements Runnable { public void run() { while (!threadDone) { try { Thread.sleep(backgroundProcessorDelay * 1000L); } catch (InterruptedException e) { ; } if (!threadDone) { Container parent = (Container) getMappingObject(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (parent.getLoader() != null) { cl = parent.getLoader().getClassLoader(); } processChildren(parent, cl); } } } protected void processChildren(Container container, ClassLoader cl) { try { if (container.getLoader() != null) { Thread.currentThread().setContextClassLoader (container.getLoader().getClassLoader()); } container.backgroundProcess(); }catch (Throwable t) {} finally { Thread.currentThread().setContextClassLoader(cl); } Container[] children = container.findChildren(); for (int i = 0; i < children.length; i++) { if (children[i].getBackgroundProcessorDelay() <= 0) { processChildren(children[i], cl); } } } }
ContainerBackgroundProcessor是ContainerBase的内部类,
在他的run方法里,有一个while循环定期的调用它的processChildren方法
发表评论
-
21,tomcat关闭钩子
2012-11-22 20:35 6630在很多环境下,在关闭应用程序的时候需要做一些清理工作。问题在于 ... -
20,tomcat的XML解析---digester
2012-11-22 20:07 1554tomcat使用server.xml配置属性信息Tomcat使 ... -
19tomcat的服务器和服务
2012-11-20 20:10 1074Server服务器 Server接口表示整个Catalina ... -
18,tomcat的主机(host)和引擎
2012-11-16 09:13 2347如果需要在一个Tomcat部署中部署多个上下文,需要使用一个主 ... -
附,listener、 filter、servlet 加载顺序及其详解
2012-11-15 09:10 982一、 1、启动一个WEB项 ... -
16,tomcat中StandardWrapper实现
2012-11-14 18:28 3883Wrapper接口在Catalina中的标准实现Standar ... -
15,tomcat安全
2012-11-14 09:02 1197有些web应用程序的内容是有限制的,只允许有权限的用户在提供正 ... -
14,tomcat session管理
2012-11-14 09:01 1101Catalina通过一个叫管理器的组建来完成Session的管 ... -
13.tomcat加载器
2012-11-13 13:21 1374库(repository)和源(res ... -
12,tomcat日志处理
2012-11-13 13:15 1247日志系统是一个记录信息的组件。在Catalina中,日志系统是 ... -
附:JAVA事件处理--观察者模式
2012-11-12 10:33 998简单地说,观察者模式 ... -
11.tomcat生命周期
2012-11-12 10:26 984Catalina由多个组件组成,当Catalina启动的 ... -
10.容器
2012-11-12 10:12 1349容器是一个处理用户servlet请求并返回对象给we ... -
9.Tomcat的默认连接器
2012-11-12 08:52 1177Tomcat连接器是一个可以插入servlet容器的独立模块, ... -
8.连接器
2012-11-12 08:46 935一个可以创建更好的请 ... -
7,Facade外观模式
2012-11-08 11:28 945外观模式:为子系统中的一组接口提供了一个一致的界面,此模式定义 ... -
6,一个简单的servlet容器
2012-11-08 11:10 847总的来说,一个全功能的servlet容器会为servlet的每 ... -
5.javax.servlet.Servlet接口
2012-11-08 09:18 947javax.servlet.Servlet接口Servlet编 ... -
4,一个简单的tomcat
2012-11-07 18:10 934流程图如下 -
3.ServerSocket 与 Socket的区别
2012-11-07 16:56 11711.1 ServerSocket类创建 ...
相关推荐
StandardContext是Tomcat中的核心组件之一,它负责管理和维护一个Web应用程序。每个Web应用程序在Tomcat中都有一个对应的StandardContext实例,它管理着Web应用的上下文、类加载器、session配置、过滤器链等关键...
Spring Boot启动过程(六)之内嵌Tomcat中StandardHost、StandardContext和StandardWrapper的启动教程详解 Spring Boot是一个基于Java的开源框架,用于快速开发Web应用程序。它提供了许多便捷的功能和配置,包括...
嵌入Tomcat是一种将Apache Tomcat服务器直接集成到Java应用程序中的技术,这使得应用程序能够独立于传统的Web服务器环境运行,增强了应用的灵活性和可移植性。本文将深入探讨嵌入Tomcat的基本概念、优势以及其实现...
在源码中,可以看到Catalina如何通过`org.apache.catalina.core.StandardEngine`、`org.apache.catalina.core.StandardHost`和`org.apache.catalina.core.StandardContext`来管理Web应用程序的生命周期。理解这些类...
2. **加载Classpath**:在启动脚本中,通过关键字`CLASSPATH`指定`bin\bootstrap.jar`等JAR包的位置,这些JAR包包含了启动Tomcat所需的类和资源。 3. **主类加载**:脚本中通过关键字`MAINCLASS`指定了主类`org....
API编程在Tomcat中扮演着核心角色,允许开发者深入理解和操作Tomcat的各种功能。 一、Tomcat API简介 Tomcat的API提供了对服务器内部组件的访问,包括Servlet、JSP、连接器(Connector)、容器(Container)等。...
《深入剖析Tomcat源码》是一本专注于解析Apache Tomcat服务器内部工作原理的书籍,而提供的压缩包文件正是这本书中的源代码示例。Tomcat作为一款广泛应用的开源Java Servlet容器,其源码对于理解Web应用服务器的工作...
Tomcat提供自动部署和管理Web应用的功能,这涉及到`StandardContext`和`LifeCycle`接口的实现。 6. **安全管理**: Tomcat的安全特性包括用户认证、角色授权等,这在`org.apache.catalina.security`和`org.apache...
在IT行业中,深入理解Web服务器的内部工作原理是至关重要的,特别是对于Java开发者而言,Tomcat作为最常用的Servlet容器,其源代码的阅读能够帮助我们更好地优化应用性能、解决复杂问题以及理解HTTP协议的实现。...
通过对Tomcat 8.0源码的学习,开发者能够更深入地理解Web服务器的工作机制,从而更好地优化应用性能,解决复杂问题,甚至参与到Tomcat的贡献和维护中。这是一条通往Java Web高级开发者之路的必经之路。
TomCat API允许开发者通过编程方式动态部署和卸载应用,例如使用`org.apache.catalina.core.StandardContext`类进行上下文配置。 3. **连接器(Connector)**:TomCat通过`Connector`组件与外界进行通信,接收和...
在本文中,我们将深入探讨Tomcat 4.1.40的源代码,揭示其内部工作原理,帮助开发者更好地理解和优化他们的应用程序。 首先,Tomcat 4.1.40是Tomcat历史上的一个早期版本,发布于2004年,尽管现在最新的版本已经发展...
【描述】:"理解Tomcat中的Filter内存马,涉及servlet-api以及Tomcat组件动态注册的实现,关注Filter的生命周期和内存马的创建思路。" 在Java Web开发中,Tomcat作为常用的Servlet容器,其内部机制包括了对Filter的...
接着,从描述中的链接下载Tomcat的源码,这里是Apache-tomcat-8.5.5。解压后,你会看到一个结构清晰的目录,包含多个子目录和文件,如`bin`、`conf`、`lib`、`webapps`等。`bin`目录包含启动和停止Tomcat的脚本,`...
Tomcat 6.0系列是一个较旧的版本,但它仍然是许多开发人员学习和测试环境中的常用选择,因为它轻量级且易于配置。 在"apache-tomcat-6.0.16.zip"中,你可以找到以下关键组成部分: 1. **bin**:包含启动和停止...
5. **Pipeline和Valve**: Tomcat的请求处理管道,Valve是管道中的处理单元,可以通过自定义Valve实现特定功能。 通过对Tomcat源码的分析,开发者可以更好地理解其工作原理,从而优化性能、解决运行问题,或者开发出...
在"apache-tomcat-6.0.16.zip"文件中,包含了Tomcat运行所需的各种jar包,如`catalina.jar`、`jasper.jar`、`servlet-api.jar`等。这些jar包分别承担了不同的功能:`catalina.jar`是Tomcat的主要执行引擎,负责...
在`conf/tomcat-users.xml`中配置用户和角色,通过`Realm`组件实现认证,`Role`和`User`定义了权限,`AccessController`处理具体的访问控制逻辑。 8. **部署与热部署** Tomcat支持自动部署和热部署。当`webapps`...