The Pipeline Interface
我们提到的Pipeline接口的第一个方法invoke方法,这个方法是容器用来调用在pipeline中的valve和basic valve的。Pipeline接口允许你使用它的addValve方法来添加一个新的valve和使用removeValve方法来移除一个valve。最后,你使用它的setBasic方法给pipeline来指定一个basic valve和它的getBasic方法获取basic valve。basic valve是在最后被调用的,它负责处理request和相应的response。下面是Pipeline接口:
Listing 5.3: The Pipeline interface
package org.apache.catalina;
import java.io.IOException;
import javax.servlet.ServletException;
public interface Pipeline {
public Valve getBasic();
public void setBasic(Valve valve);
public void addValve(Valve valve);
public Valve[] getValves();
public void invoke(Request request, Response response)
throws IOException, ServletException;
public void removeValve(Valve valve);
}
The Valve Interface
Valve接口代表了一个valve,这个组件负责处理一个request。这个接口有两个方法:invoke和getInfo。invoke方法在前面已经讨论了。getInfo方法返回关于valve实现的信息。
Listing 5.4: The Valve interface
package org.apache.catalina;
import java.io.IOException;
import javax.servlet.ServletException;
public interface Valve {
public String getInfo();
public void invoke(Request request, Response response,
ValveContext context) throws IOException, ServletException;
}
The ValveContext Interface
这个接口有两个方法:invokeNext方法在前面讨论了,getInfo方法返回ValveContext实现的信息。
Listing 5.5: The ValveContext interface
package org.apache.catalina;
import java.io.IOException;
import javax.servlet.ServletException;
public interface ValveContext {
public String getInfo();
public void invokeNext(Request request, Response response)
throws IOException, ServletException;
}
The Contained Interface
一个valve类可以选择性地实现org.apache.catalina.Contained接口。这个接口表明实现了该接口的类是最多和一个容器实例相关联的。
Listing 5.6: The Contained interface
package org.apache.catalina;
public interface Contained {
public Container getContainer();
public void setContainer(Container container);
}
The Wrapper Interface
org.apache.catalina.Wrapper接口代表了一个wrapper。一个wrapper代表了一个独立的servlet定义的容器。Wrapper接口继承自Container,再添加了一些其他方法。Wrapper的实现负责管理它们底层的servlet类的servlet生命周期。例如:调用servlet的init,service和destroy方法。一个wrapper是容器的最底层,你就不能向它里面添加子容器。如果你向它里面调用addChild方法添加子容器,这时Wrapper会抛出一个IllegalArgumantException异常。
Wrapper接口的重要方法包括:allocate和load。allocate方法分配一个这wrapper所代表的servlet初始化实例。allocate方法必须考虑到这个servlet是否是实现了javax.servlet.SingleThreadModel接口,我们在后面十一章讨论。load方法加载和实例化一个wrapper所代表的servlet。
public javax.servlet.Servlet allocate() throws
javax.servlet.ServletException;
public void load() throws javax.servlet.ServletException;
The Context Interface
一个context是代表了一个web应用的容器。一个context通常有一个或多个子容器。
重要的方法包括addWrapper,createWrapper等。这接口将在十二章详细讨论。
The Wrapper Application
这个应用程序演示怎么编写一个小的容器模块。核心类是ex05.pyrmont.core.SimpleWrapper,一个Wrapper接口的实现。SimpleWrapper类包含了一个Pipeline(实现了ex05.pyrmont.core.SimplePipeline类)和使用Loader(实现了ex05.pyrmont.core.SimpeLoader)来加载servlet。Pipeline包含了一个basic valve(ex05.pyrmont.core.SimpleWrapperValve)和两个valve(ex05.pyrmont.core.ClientIPLoggerValve 和ex05.pyrmont.core.HeaderLoggerValve)
类图:
wrapper包装了在前几章使用过的ModernServlet。这个应用程序证实了你可以使用一个只有一个wrapper组成的servlet容器。
ex05.pyrmont.core.SimpleLoader
在容器中加载servlet类的任务分配给Loader来完成这个功能。在这个应用中,SimpleLoader类就是Loader实现。它知道servlet类的路径,它的getClassLoader方法返回一个java.lang.ClassLoader实例来搜索servlet类的路径。SimpleLoader类声明了三个变量。第一个是WEB_ROOT,它指向能找到servlet类所在的目录。
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "webroot";