一个wrapper表示一个容器,这个容器盛放了每个单独的Servlet。因此,一个wrapper不能有一个子容器,它的addChild方法不应该被调用。如果调用了,将获得一个java.lang.IllegalStateException。下面是StandardWrapper类中addChild方法的实现。
public void addChild(Container child) {
throw new IllegalStateException
(sm.getString("StandardWrapper.notChild"));
}
一个wrapper的父类必须是一个上下文的实现。如果传递的不是一个上下文的容器给它,它的setParent方法将抛出一个java.lang.IllegalStateException.
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方法。init方法需要一个ServletConfig和实现了ServletConfig接口的StandardWrapper类,因此本质上,一个StandardWrapper对象可以将自身传递给init方法。然而,StandardWrapper类需要对Servlet隐藏起public方法。为了完成这个,StandardWrapper类封装自身为一个StandardWrapperFacade的实例。图11.2显示了StandardWrapperFacade与StandardWrapper之间的关系。两者都实现了ServletConfig接口。
这里将StandardWrapper对象传递给StandardWrapperFacade类的构造器。
private StandardWrapperFacade facade = new StandardWrapperFacade(this);
StandardWrapperFacade类有类型为ServletConfig的成员变量。
private ServletConfig config=null;
当一个StandardWrapperFacade的实例在StandardWrapperr对象中创建的时候,StandardWrapperFacade的构造方法被传入这个包含的StandardWrapper对象,随后构造方法将传入的参数赋值给config变量。
之后,当StandardWrapper类调用这个Servlet实例的init方法的时候,它传递了一个StandardWrapperFacade的实例。从servlet内部调用ServletConfig的上述四个方法仅仅是调用StandardWrapper类中对应实现的四个方法。
public String getServletName() {
return config.getServletName();
}
public String getInitParameter(String name) {
return config.getInitParameter(name);
}
public Enumeration getInitParameterNames() {
return config.getInitParameterNames();
}
调用getServletContext方法有点复杂
public ServletContext getServletContext() {
ServletContext theContext = config.getServletContext();
if ((theContext != null) && (theContext instanceof
ApplicationContext))
theContext = ((ApplicationContext) theContext).getFacade();
return (theContext);
}
这个方法调用了StandardWrapper类的getServletContext方法,却返回了ServletContext的门面实例而不是ServletContext对象本身。