Tomcat学习之Wrapper
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
Tomcat学习之Wrapper的更多相关文章
- Tomcat 学习进阶历程之Tomcat架构与核心类分析
前面的http及socket两部分内容,主要是为了后面看Tomcat源代码而学习的一些网络基础.从这章開始.就開始实际深入到Tomcat的'内在'去看一看. 在分析Tomcat的源代码之前,准备先看一 ...
- Tomcat学习—Tomcat的简介和目录以及配置文件介绍(Windows环境)
tomcat学习(8) 版权声明:本文为博主原创文章,未经博主允许不得转载. 今天学习TOMCAT,主要学习的是Tomcat的目录结构,配置文件! 1:Tomcat简介 Tomcat 服务器是一个免费 ...
- Tomcat学习之ClassLoader
Tomcat学习之ClassLoader 2012-09-04 22:19 8993人阅读 评论(4) 收藏 举报 分类: WEB服务器(13) 版权声明:本文为博主原创文章,未经博主允许不得转载 ...
- tomcat学习步骤,附带打破双亲委派模型企业应用实战
1. tomcat入门 入门模块仅做学习大纲梳理,忽略了具体操作指引. Tomcat的三种部署模式: 简单架构模型 连接器的非阻塞模式(NIO) 通道(Channel).缓冲区(Buffer).选择器 ...
- Tomcat学习记录
阅读摘录如下: 本质 Tomcat最本质就是个能运行JSP/Servlet的Web服务器 , 因此最典型的应用就是用户通过浏览器访问服务器,Tomcat接收到请求后转发给Servlet,由Servle ...
- Tomcat 学习笔记二
学习一 java.bean.PropertyChangeListener用来监听bean类的属性值改变.当改变时同时执行对应事件.而且是线程安全的.tomcat用此reload的Boolean值改变是 ...
- Tomcat ----> 学习笔记
源码之几个常见类和接口的关系 在学习Servlet的时候经常见到以下几个合成单词和非合成单词:Servlet.GenericServlet.HttpServlet.它们之间有联系的.接下来我把它们的联 ...
- Tomcat学习总结(7)——Tomcat与Jetty比较
Jetty 基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器. 它有一个基本数据模型,这个数据模型就是 Handler(处理 ...
- Tomcat学习总结(3)——Tomcat优化详细教程
Tomcat是我们经常使用的 servlet容器之一,甚至很多线上产品都使用 Tomcat充当服务器.而且优化后的Tomcat性能提升显著,本文从以下几方面进行分析优化. 一.内存优化 默认情况下To ...
随机推荐
- iOS提交到appstore的新要求
本文转载至http://blog.csdn.net/kqygww/article/details/41277555 64-bit and iOS 8 Requirements for New ...
- 46、PopWindow工具类
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http: ...
- 编写自己的cp命令
有时候要对整个目录做备份,修改cp1.c使得当两个参数都是目录时,把第一个目录中的所有文件复制到第二个目录中,文件名不变.那么该如何实现? 我们先来看看cp1.c的实现方式,它从一个文件中读取数据然后 ...
- 【BZOJ2870】最长道路tree 点分治+树状数组
[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来 ...
- CSS 关于让页面的高度达到电脑屏幕的底部
.sidebar:before {content: "";display: block;width: 190px;position: fixed;bottom: 0;top: 0; ...
- Json工具类库之Gson实战笔记
日常接口的数据传输通常使用xml或者json来传递数据,xml较庞大但是描述数据能力十分出众,json数据结构较小而且支持ajax传输,xml在数据传输和解析资源占用都比较逊色于json.因此日常的接 ...
- 【转】【Spring实战】Spring注解配置工作原理源码解析
一.背景知识 在[Spring实战]Spring容器初始化完成后执行初始化数据方法一文中说要分析其实现原理,于是就从源码中寻找答案,看源码容易跑偏,因此应当有个主线,或者带着问题.目标去看,这样才能最 ...
- js在页面输出信息的几种方式alert,confirm,prompt,document.write
- Ubuntu16.04安装Chrome浏览器及解决root不能打开的问题
1. 安装桌面(emmm,不知道是否只执行第二个命令就行) # apt-get install gonme# apt-get install ubuntu-desktop2. 安装Chrome浏览器 ...
- (扫盲)C#中out和ref之间的区别
首先:两者都是按地址传递的,使用后都将改变原来参数的数值. 其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所 ...