- 浏览: 68667 次
- 性别:
- 来自: 成都
最新评论
-
qiaohhgz:
public static void String chang ...
一图和几句话解决java参数传值问题 -
ocaicai:
虽然我看懂了你的意思,但是我依然觉得表达得有些欠妥!
一图和几句话解决java参数传值问题 -
ql0722:
特别赞同第二条第三条
如果我再年轻几岁 -
zzc_zj:
很好的知识点,学习了
数据库查询select原理 -
dai03070609:
[url][/url][flash=200,200][/fla ...
数据库查询select原理
The Loader Interface
在web应用里加载servlet和加载其它类都是有一定的规则的。例如:应用里的一个servlet可以使用部署在WEB-INF/classes目录及其子目录下的类。但是,servlet不能访问其它类,甚至是包含在JVM运行的Tomcat的CLASSPATH下的类。同样一个servlet也只能访问WEB-INF/lib目录下的类库,不能访问其他目录下的类库。
Tomcat的加载器代表了一个web应用的加载器,而不是一个类加载器。一个加载器必须实现org.apache.catalina.Loader接口。这个加载器实现使用一个
org.apache.catalina.loader.WebappClassLoader类表示的特定类的加载器。你可以在一个web加载器中使用Loader接口的getClassLoader方法来获取一个ClassLoader。
Loader接口定义了与一个仓库(repository)集合一起工作的方法。一个应用的WEB-INF/classes和WEB-INF/lib是目录作为仓库而被添加。Loader接口的addRepository方法用来添加一个仓库,findRepositories方法返回包含了所有仓库的一个数组。
一个Tomcat的加载器实现通常和是一个context相关联的,Loader接口的getContainer和setContainer方法用来在它们之间建立联系。如果在一个context里有一个或多个类被改变,加载器也支持重新加载。这样,servlet程序员编译一个servlet或者一个类,这个新的类在不需要重启Tomcat的情况下会被重新加载。为了实现重新加载,Loader接口有modified方法。在一个加载器实现里,modified方法在仓库中一个或多个类改变了,就返回true。但是一个加载器不会重新加载它自己本身。它调用Context接口的reload方法。其它两个方法:setReloadable和getReloadable用来决定是否使用重新加载这个功能。默认情况,Context的标准实现(org.apache.catalina.core.StandardContext),重新加载是关闭的。要打开context的重新加载功能,你需要在server.xml中添加一个Context元素:
一个加载器实现可以被告知是否使用委托,把它委托给一个父类类加载器。这样,Loader接口提供getDelegate和setDelegate方法。
Catalina提供org.apache.catalina.loader.WebappLoader作为一个Loader接口的实现。WebappLoader对象包含一个org.apache.catalina.loader实例。WebappClassLoader类继承了java.net.URLClassLoader类。
注意:在任何时候,要把容器与一个加载器相关联都需要一个servlet类。当它的invoke方法被调用,容器首先调用加载器的getClassLoader方法来获取类加载器。然后,容器调用类加载器的loadClass方法来加载servlet类。
类图如下:
The Reloader Interface
为了支持自动重新加载,一个类加载器实现必须实现org.apache.catalina.loader.Reloader接口。
它最重要的方法是modified。如果在web应用中的一个或多个servlet或类发生变化,它就返回true。它的addRepository方法用来添加一个仓库,findRepositories方法返回在实现了Reloader的类加载器里所有仓库一个字符串数组。
The WebappLoader Class
org.apache.catalina.loader.WebappLoader类是Loader接口的实现,它代表一个负责为web应用加载类的web应用加载器。WebappLoader创建一个org.apache.catalina.loader实例。WebappClassLoader作为它的类加载器。就像其它Catalina组件一样,WebappLoader实现了org.apache.catalina.Lifecycle接口,它被与它相关联的容器启动和停止。WebappLoader类也实现了java.lang.Runnable接口,它可以指定一个线程重复调用它的类加载器的modified方法。如果modified方法返回true,WebappLoader实例通知它的相关容器(本例是一个context)。
通过Context,类重新加载,而不是通过WebappLoader。
当WebappLoader类的start方法被调用时,有几个重要的任务:
Creating a class loader 创建一个类加载器
Setting repositories . 设置仓库
Setting the class path 设置类路径
Setting permissions 设置权限
Starting a new thread for auto-reload. 开始一个用于自动重新加载的新线程
下面详细讲解:
Creating A Class Loader
要加载类,一个WebappLoader实例持有一个内部类加载器。你可以回顾Loader接口:这个接口提供getClassLoader方法,但是这里没有setClassLoader方法。此外,你不能实例化一个类加载器和把它传递给WebappLoader。是不是它意味着WebappLoader不能灵活地与一个没有默认的类加载器工作?
答案是否定的。WebappLoader提供getLoaderClass和setLoaderClass方法来获取和改变它的private变量loaderClass的值。这个变量是一个代表了类加载器类名字的字符串。默认情况下,loaderClass的值是:org.apache.catalina.loader.WebappClassLoader。如果你愿意,你可以创建你自己的类加载器,它继承自WebappClassLoader。调用setLoaderClass方法强制WebappLoader使用你的特定的类加载器。当它启动了,WebappLoader将通过调用它的privatecreateClassLoader方法来创建一个WebappClassLoader实例。
使用WebappClassLoader加载器以外的其它类加载器是可能的。注意:createClassLoader方法返回一个WebappClassLoader。如果你的特定的类加载器没有继承WebappClassLoader的话,这个方法将会抛出一个异常。
Setting Repositories
WebappLoader类的start方法调用setRepositories方法来为它的类加载器添加仓库。WEB-INF/classes目录被传递给类加载器的addRepository方法。WEB-INF/lib目录被传递给类加载器的setJarPath方法。这种方式,类加载器将能够加载在WEB-INF/classes目录下的类和部署在WEB-INF/lib目录下的所有类库。
Setting the Class Path
这个任务是通过start方法,调用setClassPath方法。setClassPath方法指配一个字符串给servlet context的一个属性。这个字符串包含了Jasper JSP编译器的类路径信息。
Setting Permissions
如果在运行Tomcat的时候使用了安全管理器,setPermissions方法添加访问权限给类加载器让它可以访问必要的目录,如:WEB-INF/classes和WEB-INF/lib。如果没有使用安全管理器,这个方法就马上返回。
Starting a New Thread for Auto-Reload
WebappLoader支持自动重新加载。如果在WEB-INF/classes或WEB-INF/lib目录下的类被重编译,在不重启动Tomcat的情况下就可以自动地重新加载这个类。WebappLoader有一个线程每隔X秒时间就检查每一个资源时间戳。这里的X是定义的变量值:checkInterval。默认值是15,表示每隔15秒的时间就为是否需要重新加载做一次时间戳检查。getCheckInterval和setCheckInterval方法用来访问这个变量。
在Tomcat 4的WebappLoader实现了java.lang.Runnable接口来支持重新加载:
注意:Tomcat 5中检查类是否变化这个任务:通过org.apache.catalina.core.StandardContext 对象的backgroundProcess方法完成的。这个方法在每隔一段时间将会被调用。在org.apache.catalina.core.ContainerBase类里的一个特定的线程,ContainerBase是StandardContext的父类。检查ContainerBase类的ContainerBackgroundProcessor内部类实现了Runnable。
它的核心部分,run方法包含一个while循环,它在started变量被设置为false时结束循环:
通过checkInterval这个变量,等待(sleep)指定的时间间隔。
任何被加载的类通过调用WebappLoader实例的类加载器的modified方法来检查它们是否被改变。如果没有,continue。
如果一个类发生了改变,调用notifyContext的private变量告知与WebappLoader相关联的Context来重新加载这个类。
notifyContext方法:
notifyContext方法不会直接调用Context接口的reload方法。它实例化内部类WebappContextNotifier和传递线程对象,然后调用它的start方法。这种方式,reload的执行将会在另一个线程里面执行。下面是WebappContextNotifier类:
The WebappClassLoader Class
org.apache.catalina.loader.WebappClassLoader类代表负责为web应用加载类的类加载器。WebappClassLoader继承自java.net.URLClassLoader类,这个类用来加载前面几章中应用的java类。
WebappClassLoader的设计是出于优化和安全来考虑的。例如:它缓存先前已经被加载的类来增强性能。它也缓存它没找到的类的名字,以至于下一次同样的类被请求加载时,这个类加载器在不需要先尝试去找到他们就可以抛出ClassNotFoundException异常。WebappClassLoader搜索位于仓库列表下的类和指定JAR文件里面的类。
出于安全性,WebappClassLoader类不允许加载某些类。这些类被存储在一个叫做triggers的字符串数组,通常有一个成员:
也不用首先委托给系统类加载器,不允许你加载属于这些包及其子包下的类:
然我们看看这个类怎么缓存和加载类
Caching
为了获取更好的性能,被加载的类会被缓存起来,以便下次在这个类需要时不需要再次加载。它可以从缓存中取出来。缓存可以在本地处理,缓存是被WebappClassLoader实例管理的。此外,java.lang.ClassLoader维护一个之前被加载过的类的Vector,以防止它这些类被垃圾回收。这种情况,缓存是被它的父类管理的。
每个类会被当做一个资源,它(WEB-INF/classes下或JAR文件里的类文件)是通过WebappClassLoader来加载的。一个资源由org.apache.catalina.loader.ResourceEntry类代表。一个ResourceEntry实例持有类的代表、最后的更改日期、清单(Manifest)等等的字节数组。
所有的缓存资源被存储在一个叫做resourceEntries的HashMap中。它的key是资源名。所有没有找到的资源被存储在另外一个叫做notFoundResources的HashMap中。
Loading Classes
当加载一个类,WebappClassLoader遵守下面的规则:
所有之前加载的类被缓存,所有首先会检查本地缓存
如果没有在本地缓存里找到,就通过调用java.lang.ClassLoader类的findLoadedClass方法检查缓存
若果两个缓存里都没找到,使用系统的类加载器,防止web应用重写J2EE里的类
如果使用了安全管理器,检查这个类是否允许加载。如果这个类不允许加载,抛出一个ClassNotFoundException异常。
如果delegate标识符是on或者如果这个想要被加载类是属于trigger里面包含的包下,使用父类加载器来加载这个类,如果父类加载器是null,使用系统类加载器。
从当前仓库加载这个类。
如果在当前仓库里没有发现这个类,如果delegation标识符不是on,使用父类加载器。如果父类加载器是null,使用系统类加载器。
如果这个类还是没有被发现,就抛出一个ClassNotFoundException异常。
The Application
Context的标准实现是org.apache.catalina.core.StandardContext类。这个应用实例化StandardContext类。StandardContext会在十二章中讨论。你在本章不需要知道关于这个类的详细情况。你只需要知道StandardContext它与一个监听器一起工作。它监听事件的触发。例如:START_EVENT 和STOP_EVENT。监听器必须实现org.apache.catalina.lifecycle.LifecycleListener接口,调用StandardContext类的setConfigured方法。本章的监听器就是由ex08.pyrmont.core.SimpleContextConfig类来表示。
你所需要做的是实例化StandardContext和SimpleContextConfig,然后调用org.apache.catalina.Lifecycle接口的addLifecycleListener方法用StandardContext来注册SimpleContextConfig。
使用StandardContext 的WEB-INF/classes目录下存储的servlet。这个叫做myApp是应用目录在当你第一次部署可下载的ZIP文件时被创建。告诉StandardContext实例在哪里可以找到这个应用目录,你设置一个系统属性:catalina.base 。它的值是user.dir属性。
实际上,这是BootStrap类main方法的第一行代码,然后,main方法实例化默认的连接器。
然后为两个servlet创建各自的wrapper,并实例化它们:
然后创建一个StandardContext实例,也设置context的文档库:
配置下面的元素在server.xml文件中:
然后把两个wrapper加入到context中,添加映射以便context可以定位wrapper。
下一步是实例化监听器和注册:
接下来实例化WebappLoader,然后把它与context相关联起来:
Loader loader = new WebappLoader();
context.setLoader(loader);
最后,把context和默认的连接器相关联起来,调用连接器的initialize和start方法。
下面几行简单地展示了资源的docBase的值和在类加载器里的所有仓库:
这几行让docBase和仓库的列表当你运行这个应用程序的时候会被打印出来。
docBase的值在你的机器上会有不同的值,依赖于你安装的应用.
最后,直到用户在控制台按了Enter键,就停止应用程序。不然应用就一直处于等待状态。
Running the Application
总结:web应用加载器或一个简单的加载器,是Catalina中最重要的一个组件。一个加载器负责加载类和持有一个内部类加载器。这个内部类加载器是一个特定的类,它被Tomcat用来执行某种规则来加载类。这个特定的类加载器支持缓存和检查单个或多个类是否发生变化。
注:把repository翻译为仓库
第八章 完
在web应用里加载servlet和加载其它类都是有一定的规则的。例如:应用里的一个servlet可以使用部署在WEB-INF/classes目录及其子目录下的类。但是,servlet不能访问其它类,甚至是包含在JVM运行的Tomcat的CLASSPATH下的类。同样一个servlet也只能访问WEB-INF/lib目录下的类库,不能访问其他目录下的类库。
Tomcat的加载器代表了一个web应用的加载器,而不是一个类加载器。一个加载器必须实现org.apache.catalina.Loader接口。这个加载器实现使用一个
org.apache.catalina.loader.WebappClassLoader类表示的特定类的加载器。你可以在一个web加载器中使用Loader接口的getClassLoader方法来获取一个ClassLoader。
Loader接口定义了与一个仓库(repository)集合一起工作的方法。一个应用的WEB-INF/classes和WEB-INF/lib是目录作为仓库而被添加。Loader接口的addRepository方法用来添加一个仓库,findRepositories方法返回包含了所有仓库的一个数组。
一个Tomcat的加载器实现通常和是一个context相关联的,Loader接口的getContainer和setContainer方法用来在它们之间建立联系。如果在一个context里有一个或多个类被改变,加载器也支持重新加载。这样,servlet程序员编译一个servlet或者一个类,这个新的类在不需要重启Tomcat的情况下会被重新加载。为了实现重新加载,Loader接口有modified方法。在一个加载器实现里,modified方法在仓库中一个或多个类改变了,就返回true。但是一个加载器不会重新加载它自己本身。它调用Context接口的reload方法。其它两个方法:setReloadable和getReloadable用来决定是否使用重新加载这个功能。默认情况,Context的标准实现(org.apache.catalina.core.StandardContext),重新加载是关闭的。要打开context的重新加载功能,你需要在server.xml中添加一个Context元素:
<Context path="/myApp" docBase="myApp" debug="0" reloadable="true"/>
一个加载器实现可以被告知是否使用委托,把它委托给一个父类类加载器。这样,Loader接口提供getDelegate和setDelegate方法。
Listing 8.1: The Loader interface package org.apache.catalina; import java.beans.PropertyChangeListener; public interface Loader { public ClassLoader getClassLoader(); public Container getContainer(); public void setContainer(Container container); public DefaultContext getDefaultContext(); public void setDefaultContext(DefaultContext defaultContext); public boolean getDelegate(); public void setDelegate(boolean delegate); public String getInfo(); public boolean getReloadable(); public void setReloadable(boolean reloadable); public void addPropertyChangeListener(PropertyChangeListener listener); public void addRepository(String repository); public String[] findRepositories(); public boolean modified(); public void removePropertyChangeListener(PropertyChangeListener listener); }
Catalina提供org.apache.catalina.loader.WebappLoader作为一个Loader接口的实现。WebappLoader对象包含一个org.apache.catalina.loader实例。WebappClassLoader类继承了java.net.URLClassLoader类。
注意:在任何时候,要把容器与一个加载器相关联都需要一个servlet类。当它的invoke方法被调用,容器首先调用加载器的getClassLoader方法来获取类加载器。然后,容器调用类加载器的loadClass方法来加载servlet类。
类图如下:
The Reloader Interface
为了支持自动重新加载,一个类加载器实现必须实现org.apache.catalina.loader.Reloader接口。
Listing 8.2: The Reloader interface package org.apache.catalina.loader; public interface Reloader { public void addRepository(String repository); public String[] findRepositories (); public boolean modified(); }
它最重要的方法是modified。如果在web应用中的一个或多个servlet或类发生变化,它就返回true。它的addRepository方法用来添加一个仓库,findRepositories方法返回在实现了Reloader的类加载器里所有仓库一个字符串数组。
The WebappLoader Class
org.apache.catalina.loader.WebappLoader类是Loader接口的实现,它代表一个负责为web应用加载类的web应用加载器。WebappLoader创建一个org.apache.catalina.loader实例。WebappClassLoader作为它的类加载器。就像其它Catalina组件一样,WebappLoader实现了org.apache.catalina.Lifecycle接口,它被与它相关联的容器启动和停止。WebappLoader类也实现了java.lang.Runnable接口,它可以指定一个线程重复调用它的类加载器的modified方法。如果modified方法返回true,WebappLoader实例通知它的相关容器(本例是一个context)。
通过Context,类重新加载,而不是通过WebappLoader。
当WebappLoader类的start方法被调用时,有几个重要的任务:
Creating a class loader 创建一个类加载器
Setting repositories . 设置仓库
Setting the class path 设置类路径
Setting permissions 设置权限
Starting a new thread for auto-reload. 开始一个用于自动重新加载的新线程
下面详细讲解:
Creating A Class Loader
要加载类,一个WebappLoader实例持有一个内部类加载器。你可以回顾Loader接口:这个接口提供getClassLoader方法,但是这里没有setClassLoader方法。此外,你不能实例化一个类加载器和把它传递给WebappLoader。是不是它意味着WebappLoader不能灵活地与一个没有默认的类加载器工作?
答案是否定的。WebappLoader提供getLoaderClass和setLoaderClass方法来获取和改变它的private变量loaderClass的值。这个变量是一个代表了类加载器类名字的字符串。默认情况下,loaderClass的值是:org.apache.catalina.loader.WebappClassLoader。如果你愿意,你可以创建你自己的类加载器,它继承自WebappClassLoader。调用setLoaderClass方法强制WebappLoader使用你的特定的类加载器。当它启动了,WebappLoader将通过调用它的privatecreateClassLoader方法来创建一个WebappClassLoader实例。
Listing 8.3: The createClassLoader method private WebappClassLoader createClassLoader() throws Exception { Class clazz = Class.forName(loaderClass); WebappClassLoader classLoader = null; if (parentClassLoader == null) { // Will cause a ClassCast if the class does not extend // WebappClassLoader, but this is on purpose (the exception will be // caught and rethrown) classLoader = (WebappClassLoader) clazz.newInstance(); // in Tomcat 5, this if block is replaced by the following: // if (parentClassLoader == null) { // parentClassLoader = hread.currentThread().getContextClassLoader(); // } else { Class[] argTypes = { ClassLoader.class }; Object[] args = { parentClassLoader }; Constructor constr = clazz.getConstructor(argTypes); classLoader = (WebappClassLoader) constr.newInstance(args); } return classLoader; }
使用WebappClassLoader加载器以外的其它类加载器是可能的。注意:createClassLoader方法返回一个WebappClassLoader。如果你的特定的类加载器没有继承WebappClassLoader的话,这个方法将会抛出一个异常。
Setting Repositories
WebappLoader类的start方法调用setRepositories方法来为它的类加载器添加仓库。WEB-INF/classes目录被传递给类加载器的addRepository方法。WEB-INF/lib目录被传递给类加载器的setJarPath方法。这种方式,类加载器将能够加载在WEB-INF/classes目录下的类和部署在WEB-INF/lib目录下的所有类库。
Setting the Class Path
这个任务是通过start方法,调用setClassPath方法。setClassPath方法指配一个字符串给servlet context的一个属性。这个字符串包含了Jasper JSP编译器的类路径信息。
Setting Permissions
如果在运行Tomcat的时候使用了安全管理器,setPermissions方法添加访问权限给类加载器让它可以访问必要的目录,如:WEB-INF/classes和WEB-INF/lib。如果没有使用安全管理器,这个方法就马上返回。
Starting a New Thread for Auto-Reload
WebappLoader支持自动重新加载。如果在WEB-INF/classes或WEB-INF/lib目录下的类被重编译,在不重启动Tomcat的情况下就可以自动地重新加载这个类。WebappLoader有一个线程每隔X秒时间就检查每一个资源时间戳。这里的X是定义的变量值:checkInterval。默认值是15,表示每隔15秒的时间就为是否需要重新加载做一次时间戳检查。getCheckInterval和setCheckInterval方法用来访问这个变量。
在Tomcat 4的WebappLoader实现了java.lang.Runnable接口来支持重新加载:
Listing 8.3: The run method public void run() { if (debug >= 1) log("BACKGROUND THREAD Starting"); // Loop until the termination semaphore is set while (!threadDone) { // Wait for our check interval threadSleep(); if (!started) break; try { // Perform our modification check if (!classLoader.modified()) continue; } catch (Exception e) { log(sm.getString("webappLoader.failModifiedCheck"), e); continue; } // Handle a need for reloading notifyContext(); break; } if (debug >= 1) log("BACKGROUND THREAD Stopping"); }
注意:Tomcat 5中检查类是否变化这个任务:通过org.apache.catalina.core.StandardContext 对象的backgroundProcess方法完成的。这个方法在每隔一段时间将会被调用。在org.apache.catalina.core.ContainerBase类里的一个特定的线程,ContainerBase是StandardContext的父类。检查ContainerBase类的ContainerBackgroundProcessor内部类实现了Runnable。
它的核心部分,run方法包含一个while循环,它在started变量被设置为false时结束循环:
通过checkInterval这个变量,等待(sleep)指定的时间间隔。
任何被加载的类通过调用WebappLoader实例的类加载器的modified方法来检查它们是否被改变。如果没有,continue。
如果一个类发生了改变,调用notifyContext的private变量告知与WebappLoader相关联的Context来重新加载这个类。
notifyContext方法:
Listing 8.4: The notifyContext method private void notifyContext() { WebappContextNotifier notifier = new WebappContextNotifier(); (new Thread(notifier)).start(); }
notifyContext方法不会直接调用Context接口的reload方法。它实例化内部类WebappContextNotifier和传递线程对象,然后调用它的start方法。这种方式,reload的执行将会在另一个线程里面执行。下面是WebappContextNotifier类:
Listing 8.5: The WebappContextNotifier inner class protected class WebappContextNotifier implements Runnable { public void run() { ((Context) container).reload(); } 当一个WebappContextNotifier实例传递给一个Thread时,这个Thread对象调用它的start方法。WebappContextNotifier实例的run方法将会被执行。run方法调用Context接口的reload方法。
The WebappClassLoader Class
org.apache.catalina.loader.WebappClassLoader类代表负责为web应用加载类的类加载器。WebappClassLoader继承自java.net.URLClassLoader类,这个类用来加载前面几章中应用的java类。
WebappClassLoader的设计是出于优化和安全来考虑的。例如:它缓存先前已经被加载的类来增强性能。它也缓存它没找到的类的名字,以至于下一次同样的类被请求加载时,这个类加载器在不需要先尝试去找到他们就可以抛出ClassNotFoundException异常。WebappClassLoader搜索位于仓库列表下的类和指定JAR文件里面的类。
出于安全性,WebappClassLoader类不允许加载某些类。这些类被存储在一个叫做triggers的字符串数组,通常有一个成员:
private static final String[] triggers = { "javax.servlet.Servlet" // Servlet API };
也不用首先委托给系统类加载器,不允许你加载属于这些包及其子包下的类:
private static final String[] packageTriggers = { "javax", // Java extensions "org.xml.sax", // SAX 1 & 2 "org.w3c.dom", // DOM 1 & 2 "org.apache.xerces", // Xerces 1 & 2 "org.apache.xalan" // Xalan };
然我们看看这个类怎么缓存和加载类
Caching
为了获取更好的性能,被加载的类会被缓存起来,以便下次在这个类需要时不需要再次加载。它可以从缓存中取出来。缓存可以在本地处理,缓存是被WebappClassLoader实例管理的。此外,java.lang.ClassLoader维护一个之前被加载过的类的Vector,以防止它这些类被垃圾回收。这种情况,缓存是被它的父类管理的。
每个类会被当做一个资源,它(WEB-INF/classes下或JAR文件里的类文件)是通过WebappClassLoader来加载的。一个资源由org.apache.catalina.loader.ResourceEntry类代表。一个ResourceEntry实例持有类的代表、最后的更改日期、清单(Manifest)等等的字节数组。
The ResourceEntry class is given in Listing 8.6. Listing 8.6: The ResourceEntry class. package org.apache.catalina.loader; import java.net.URL; import java.security.cert.Certificate; import java.util.jar.Manifest; public class ResourceEntry { public long lastModifled = -1; // Binary content of the resource. public byte[] binaryContent = null; public Class loadedClass = null; // URL source from where the object was loaded. public URL source = null; // URL of the codebase from where the object was loaded. public URL CodeBase = null; public Manifest manifest = null; public Certificate[] certificates = null; }
所有的缓存资源被存储在一个叫做resourceEntries的HashMap中。它的key是资源名。所有没有找到的资源被存储在另外一个叫做notFoundResources的HashMap中。
Loading Classes
当加载一个类,WebappClassLoader遵守下面的规则:
所有之前加载的类被缓存,所有首先会检查本地缓存
如果没有在本地缓存里找到,就通过调用java.lang.ClassLoader类的findLoadedClass方法检查缓存
若果两个缓存里都没找到,使用系统的类加载器,防止web应用重写J2EE里的类
如果使用了安全管理器,检查这个类是否允许加载。如果这个类不允许加载,抛出一个ClassNotFoundException异常。
如果delegate标识符是on或者如果这个想要被加载类是属于trigger里面包含的包下,使用父类加载器来加载这个类,如果父类加载器是null,使用系统类加载器。
从当前仓库加载这个类。
如果在当前仓库里没有发现这个类,如果delegation标识符不是on,使用父类加载器。如果父类加载器是null,使用系统类加载器。
如果这个类还是没有被发现,就抛出一个ClassNotFoundException异常。
The Application
Context的标准实现是org.apache.catalina.core.StandardContext类。这个应用实例化StandardContext类。StandardContext会在十二章中讨论。你在本章不需要知道关于这个类的详细情况。你只需要知道StandardContext它与一个监听器一起工作。它监听事件的触发。例如:START_EVENT 和STOP_EVENT。监听器必须实现org.apache.catalina.lifecycle.LifecycleListener接口,调用StandardContext类的setConfigured方法。本章的监听器就是由ex08.pyrmont.core.SimpleContextConfig类来表示。
Listing 8.6: The SimpleContextConfig class package ex08.pyrmont.core; import org.apache.catalina.Context; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; public class SimpleContextConfig implements LifecycleListener { public void lifecycleEvent(LifecycleEvent event) { if (Lifecycle.START_EVENT.equals(event.getType())) { Context context = (Context) event.getLifecycle(); context.setConfigured(true); } } }
你所需要做的是实例化StandardContext和SimpleContextConfig,然后调用org.apache.catalina.Lifecycle接口的addLifecycleListener方法用StandardContext来注册SimpleContextConfig。
使用StandardContext 的WEB-INF/classes目录下存储的servlet。这个叫做myApp是应用目录在当你第一次部署可下载的ZIP文件时被创建。告诉StandardContext实例在哪里可以找到这个应用目录,你设置一个系统属性:catalina.base 。它的值是user.dir属性。
System.setProperty("catalina.base", System.getProperty("user.dir"));
实际上,这是BootStrap类main方法的第一行代码,然后,main方法实例化默认的连接器。
Connector connector = new HttpConnector();
然后为两个servlet创建各自的wrapper,并实例化它们:
Wrapper wrapper1 = new SimpleWrapper(); wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new SimpleWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet");
然后创建一个StandardContext实例,也设置context的文档库:
Context context = new StandardContext(); // StandardContext's start method adds a default mapper context.setPath("/myApp"); context.setDocBase("myApp");
配置下面的元素在server.xml文件中:
<Context path="/myApp" docBase="myApp"/>
然后把两个wrapper加入到context中,添加映射以便context可以定位wrapper。
context.addChild(wrapper1); context.addChild(wrapper2); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern");
下一步是实例化监听器和注册:
LifecycleListener listener = new SimpleContextConfig(); ((Lifecycle) context).addLifecycleListener(listener);
接下来实例化WebappLoader,然后把它与context相关联起来:
Loader loader = new WebappLoader();
context.setLoader(loader);
最后,把context和默认的连接器相关联起来,调用连接器的initialize和start方法。
connector.setContainer(context); try { connector.initialize(); ((Lifecycle) connector).start(); ((Lifecycle) context).start();
下面几行简单地展示了资源的docBase的值和在类加载器里的所有仓库:
// now we want to know some details about WebappLoader WebappClassLoader classLoader = (WebappClassLoader) loader.getClassLoader(); System.out.println("Resources' docBase: " + ((ProxyDirContext)classLoader.getResources ()).getDocBase()); String[] repositories = classLoader.findRepositories(); for (int i=0; i<repositorles.length; i++) { System.out.println("repository: " + repositories[i]); }
这几行让docBase和仓库的列表当你运行这个应用程序的时候会被打印出来。
Resources’ docBase: C:\HowTomcatWorks\myApp repository: /WEB-INF/classes/
docBase的值在你的机器上会有不同的值,依赖于你安装的应用.
最后,直到用户在控制台按了Enter键,就停止应用程序。不然应用就一直处于等待状态。
// make the application wait until we press a key. System.in.read(); ((Lifecycle) context).stop();
Running the Application
总结:web应用加载器或一个简单的加载器,是Catalina中最重要的一个组件。一个加载器负责加载类和持有一个内部类加载器。这个内部类加载器是一个特定的类,它被Tomcat用来执行某种规则来加载类。这个特定的类加载器支持缓存和检查单个或多个类是否发生变化。
注:把repository翻译为仓库
第八章 完
发表评论
-
MyEclipse插件安装
2012-03-22 10:05 4321:先把plugin的jar文件复制到一个文件夹下 如:C:/ ... -
Hibernate框架使用技术简述
2011-03-24 10:14 1133(1)持久化对象的操 ... -
Coder 爱翻译 How Tomcat Works 第九章 第二部分
2011-01-24 15:20 1179The ManagerBase Class ManagerB ... -
Coder 爱翻译 How Tomcat Works 第九章 第一部分
2010-12-16 20:40 1264Chapter 9: Session Management ... -
Coder 爱翻译 How Tomcat Works 第八章 第一部分
2010-12-06 11:14 1097Chapter 8: Loader 在前几章 ... -
Coder 爱翻译 How Tomcat Works 第七章
2010-12-05 16:29 1197Chapter 7: Logger 日志是一 ... -
Coder 爱翻译 How Tomcat Works 第六章
2010-12-04 22:09 1173Chapter 6: Lifecycle Catalina是 ... -
Coder 爱翻译 How Tomcat Works 第五章 第三部分
2010-12-03 13:31 1163The Context Application 这章的第一个 ... -
Coder 爱翻译 How Tomcat Works 第五章 第二部分
2010-12-03 12:33 3116The Pipeline Interface 我们提到的Pi ... -
Coder 爱翻译 How Tomcat Works 第五章 第一部分
2010-11-28 16:36 1174Chapter 5: Container 一个容器是一个为s ... -
Coder 爱翻译 How Tomcat Works 第四章 第二部分
2010-11-27 15:07 1058Request Objects 在默认的连接器中org.ap ... -
Coder 爱翻译 How Tomcat Works 第四章 第一部分
2010-11-25 16:38 951Chapter 4: Tomcat Default Conne ... -
PreparedStatement字符串拼接
2010-11-18 17:21 1407这在里求JDBC中PreparedStatement的实现,我 ... -
HelloWorld的javap -verbose HelloWorld 字节码初探
2010-11-17 12:20 3129基本的HelloWorld类: public class ... -
How Tomcat Works 简单目录
2010-11-16 14:51 1446第1章:通过一个简单的HTTP服务器开始这本书的内容。构建一个 ... -
Coder 爱翻译 How Tomcat Works 第三章 第三部分
2010-11-15 19:24 1038Parsing Headers 一个HttpHeader类 ... -
Coder 爱翻译 How Tomcat Works 第三章 第二部分
2010-11-14 20:13 1093The Connector(连接器) HttpConnect ... -
回应某面试题
2010-11-10 21:31 1323上午看了一JAVAEYE的一个上机题:http://www.i ... -
quartz简单应用
2010-11-10 11:49 1002Job类:实现Job接口,接口中有一个execute()方法, ... -
coder 爱翻译 How Tomcat Works 第三章 第一部分
2010-11-05 11:41 1134第三章: Connector 在正式 ...
相关推荐
适合读者 1.jsp/servlet 开发人员,想了解 tomcat 内部机制的 coder;...2.想加入 tomcat 开发团队的 coder; 3.web 开发人员,但对软件开发很有兴趣的 coder; 4.想要对 tomcat 进行定制的 coder。
Bad Programming Practices 101 Become a Better Coder by Learning How (Not) to Program 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
- **插件扩展**:PHPCoder支持第三方插件,可以通过社区下载安装增强功能。 - **代码格式化**:使用“编辑”>“格式化代码”对代码进行整理,保持良好的编码风格。 - **搜索与替换**:利用查找和替换功能,可以在...
mediacoder 5685专业版,无普通版的限制
2. 高质量编码:MediaCoder允许用户自定义编码参数,如比特率、分辨率、帧率等,以实现高质量的编码输出,满足不同应用场景的需求,比如视频压缩、在线流媒体、移动设备播放等。 3. 强大的硬件加速:MediaCoder利用...
#### 二、Simulink HDL Coder 的主要功能特点 1. **模型到 HDL 的转换**:Simulink HDL Coder 支持将 Simulink 模型转换成 VHDL 或 Verilog HDL 代码。这些模型可以包括数学运算、信号处理、通信协议等多种类型的...
Simulink PLC Coder 支持 130 多个 Simulink 模块,包括所有的 Stateflow 结构以及大部分嵌入式 MATLAB 函数。 Simulink PLC Coder 提供了优化策略,使得内存大小减少,并且所生成的结构化文本的执行速度也得以...
Embedded Coder用于产生嵌入式处理器、目标快速原型板和大规模生产中使用的微处理器的可读的、紧凑的、快速的C和C++代码。Embedded Coder支持附加的MATLAB Coder™和Simulink Coder™配置选项,以及对生成代码的功能...
**Mediacoder基础教程** Mediacoder是一款强大的多媒体编码工具,专为音频和视频转换而设计,支持多种格式,如MP4、AVI、MKV等。本教程将深入讲解如何利用Mediacoder进行视频压制,优化视频质量,同时合理权衡码率...
Martin, "The Clean Coder: A Code of Conduct for Professional Programmers" Prentice Hall | 2011 | ISBN: 0137081073 | 256 pages | PDF | 6 MB Programmers who endure and succeed amidst swirling ...
虽然CoolCoder能够自动化大部分工作,但开发者依然可以自定义模板,对生成的代码进行微调,以满足特定项目的需求。这种灵活性确保了生成的代码既高效又符合项目风格。 6. **提高开发效率**: 使用CoolCoder,...
MediaCoder是一款功能强大的多媒体转换工具,它支持广泛的音频和视频编码格式,使用户能够轻松地在不同设备之间转换媒体文件。这款软件适用于个人用户、专业音频和视频制作人员,以及那些希望在各种设备上享受多媒体...
PHPCoder用于快速开发和调试PHP应用程序,它很容易扩展和定制,完全能够符合开发者的个性要求.PHPCoder是一个非常实用的,功能强大的编程环境,而且它是免费的!
### HDL-Coder详细教程知识点概述 #### 一、生成HDL代码前的准备工作 在开始从Simulink模型生成HDL代码之前,需要完成一系列的准备工作,确保模型能够顺利生成高质量的代码。 ##### 1.1 使用`hdlsetup`进行模型...
### MATLAB Coder 基本函数教程 #### MATLAB Coder 概述 MATLAB Coder 是一款能够将 MATLAB 代码转换成独立的 C 或 C++ 代码的强大工具。这一过程对于那些希望在非 MATLAB 环境下部署 MATLAB 代码的应用开发者来说...
MediaCoder行业版一款针对VOD及KTV视频点播行业开发的,用于转换和处理带有多音轨内容的视频节目的软件。它具备业界领先的视频编码引擎,在高性能转码的同时保持高画质,并通过丰富的视频滤镜增强画面视觉效果。作为...
MediaCoder使用说明文档, mediaCoder usermanual,
Matlab Coder是Mathworks公司推出的一款用于将Matlab代码转换成高效C代码的工具。从2004年开始,Matlab陆续在Simulink中添加了Embeded Matlab Function模块,2007年在Real-Time Workshop中引入了emlc函数(现在的...
texasinstrumentsc2000.mlpkginstall 支持TI的C2000系列工具包,要求MATLAB R2017a及其以上版本。 安装方法:打开matlab,调整路径到mlpkginstall文件所在目录;在current folder窗口里双击mlpkginstall文件即可开始...
接下来,我们讨论"magicalcoder文件去域名"的第二个方面——软件授权限制的解除。通常,商业软件会设定一定的授权机制,包括使用期限、设备数量或特定的使用环境(如特定域名)。这些限制是为了保护知识产权,防止...