Tomcat学习之Wrapper
时间:2014-12-30 13:26 来源:linux.it.net.cn 作者:IT
Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。它的父容器一般是Context,Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会抛illegalargumentexception。Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。
在StandardContext启动时,读取web.xml配置文件,配置Context之后,紧接着启动Context的一些附属组件,除此以外还加载了那些标记为"load on start"的那些wrapper
-
// Load and initialize all "load on startup" servlets
-
if (ok) {
-
loadOnStartup(findChildren());
-
}
-
public void loadOnStartup(Container children[]) {
-
-
// Collect "load on startup" servlets that need to be initialized
-
TreeMap<Integer, ArrayList<Wrapper>> map =
-
new TreeMap<Integer, ArrayList<Wrapper>>();
-
for (int i = 0; i < children.length; i++) {
-
Wrapper wrapper = (Wrapper) children[i];
-
int loadOnStartup = wrapper.getLoadOnStartup();
-
if (loadOnStartup < 0)
-
continue;
-
Integer key = Integer.valueOf(loadOnStartup);
-
ArrayList<Wrapper> list = map.get(key);
-
if (list == null) {
-
list = new ArrayList<Wrapper>();
-
map.put(key, list);
-
}
-
list.add(wrapper);
-
}
-
-
// Load the collected "load on startup" servlets
-
for (ArrayList<Wrapper> list : map.values()) {
-
for (Wrapper wrapper : list) {
-
try {
-
wrapper.load();
-
} catch (ServletException e) {
-
getLogger().error(sm.getString("standardWrapper.loadException",
-
getName()), StandardWrapper.getRootCause(e));
-
// NOTE: load errors (including a servlet that throws
-
// UnavailableException from tht init() method) are NOT
-
// fatal to application startup
-
}
-
}
-
}
-
-
}
这个方法做了两件事:
1、遍历这些wrapper,将其放入一个map中。key为启动顺序,value是同一启动顺序的servlet list,为了保护数字小的先启动,这里用了treemap这种数据结构来存储;
2、遍历这个map,依次加载对应list中的各个wrapper。由于采用的是arrayList,所以相同"load on start"值靠前的先加载
下面来看看StandardWrapper的load方法,直接调用了loadServlet方法来初始化
-
public synchronized void load() throws ServletException {
-
instance = loadServlet();
-
-
if (!instanceInitialized) {
-
initServlet(instance);
-
}
-
-
if (isJspServlet) {
-
StringBuilder oname =
-
new StringBuilder(MBeanUtils.getDomain(getParent()));
-
-
oname.append(":type=JspMonitor,name=");
-
oname.append(getName());
-
-
oname.append(getWebModuleKeyProperties());
-
-
try {
-
jspMonitorON = new ObjectName(oname.toString());
-
Registry.getRegistry(null, null)
-
.registerComponent(instance, jspMonitorON, null);
-
} catch( Exception ex ) {
-
log.info("Error registering JSP monitoring with jmx " +
-
instance);
-
}
-
}
-
}
-
private synchronized void initServlet(Servlet servlet)throws ServletException {
-
if (instanceInitialized && !singleThreadModel) return;
-
// Call the initialization method of this servlet
-
try {
-
instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet);
-
if (Globals.IS_SECURITY_ENABLED) {
-
Object[] args = new Object[] { (facade) };
-
SecurityUtil.doAsPrivilege("init", servlet, classType, args);
-
args = null;
-
} else {
-
servlet.init(facade);
-
}
-
-
instanceInitialized = true;
-
instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet);
-
} catch (UnavailableException f) {
-
//handle exception
-
}
-
}
实际上是调用了servlet的init方法,这已经是servlet的代码了,这里不再分析。
前面提到的servlet的加载只是被标识为“load on start”的那些servlet,那么其他servlet是在什么时候被加载的呢?选中StandardWrapper的initServlet方法,在eclipse中查看其调用层次如下:

会发现有个allocate方法间接调用了它,这里给出请求进入wrapper之后的方法调用时序图:
![]()

可以看出在请求进入wrapper之后,通过allocate方法从实例池栈中弹出一个servlet实例来处理这个请求,servlet实例被封装成filterChain对象,紧接着通过一系列的过滤器过滤到达servlet.service()方法,这是singleThreadModel模式的做法。在非singleThreadModel模式的情况下首次加载并初始始化servlet赋给instance字段,下次直接从这个字段中获取servlet实例,因此在非singleThreadModel模式下每次返回的是同一个servlet实例。有关singleThreadModel的具体介绍参考:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/SingleThreadModel.html
(责任编辑:IT)
Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。它的父容器一般是Context,Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会抛illegalargumentexception。Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。 在StandardContext启动时,读取web.xml配置文件,配置Context之后,紧接着启动Context的一些附属组件,除此以外还加载了那些标记为"load on start"的那些wrapper
这个方法做了两件事: 1、遍历这些wrapper,将其放入一个map中。key为启动顺序,value是同一启动顺序的servlet list,为了保护数字小的先启动,这里用了treemap这种数据结构来存储; 2、遍历这个map,依次加载对应list中的各个wrapper。由于采用的是arrayList,所以相同"load on start"值靠前的先加载 下面来看看StandardWrapper的load方法,直接调用了loadServlet方法来初始化
前面提到的servlet的加载只是被标识为“load on start”的那些servlet,那么其他servlet是在什么时候被加载的呢?选中StandardWrapper的initServlet方法,在eclipse中查看其调用层次如下:
会发现有个allocate方法间接调用了它,这里给出请求进入wrapper之后的方法调用时序图: |