Tomcat学习之Wrapper

Tomcat学习之Wrapper

分类: WEB服务器2012-08-30 22:16 1547人阅读 评论(0) 收藏 举报

tomcatservletwrapperservletslistexception

Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。它的父容器一般是Context,Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会抛illegalargumentexception。Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。

在StandardContext启动时,读取web.xml配置文件,配置Context之后,紧接着启动Context的一些附属组件,除此以外还加载了那些标记为"load on start"的那些wrapper

[java] view plaincopyprint?

  1. // Load and initialize all "load on startup" servlets
  2. if (ok) {
  3. loadOnStartup(findChildren());
  4. }

[java] view plaincopyprint?

  1. public void loadOnStartup(Container children[]) {
  2. // Collect "load on startup" servlets that need to be initialized
  3. TreeMap<Integer, ArrayList<Wrapper>> map =
  4. new TreeMap<Integer, ArrayList<Wrapper>>();
  5. for (int i = 0; i < children.length; i++) {
  6. Wrapper wrapper = (Wrapper) children[i];
  7. int loadOnStartup = wrapper.getLoadOnStartup();
  8. if (loadOnStartup < 0)
  9. continue;
  10. Integer key = Integer.valueOf(loadOnStartup);
  11. ArrayList<Wrapper> list = map.get(key);
  12. if (list == null) {
  13. list = new ArrayList<Wrapper>();
  14. map.put(key, list);
  15. }
  16. list.add(wrapper);
  17. }
  18. // Load the collected "load on startup" servlets
  19. for (ArrayList<Wrapper> list : map.values()) {
  20. for (Wrapper wrapper : list) {
  21. try {
  22. wrapper.load();
  23. } catch (ServletException e) {
  24. getLogger().error(sm.getString("standardWrapper.loadException",
  25. getName()), StandardWrapper.getRootCause(e));
  26. // NOTE: load errors (including a servlet that throws
  27. // UnavailableException from tht init() method) are NOT
  28. // fatal to application startup
  29. }
  30. }
  31. }
  32. }

这个方法做了两件事:

1、遍历这些wrapper,将其放入一个map中。key为启动顺序,value是同一启动顺序的servlet list,为了保护数字小的先启动,这里用了treemap这种数据结构来存储;

2、遍历这个map,依次加载对应list中的各个wrapper。由于采用的是arrayList,所以相同"load on start"值靠前的先加载

下面来看看StandardWrapper的load方法,直接调用了loadServlet方法来初始化

[java] view plaincopyprint?

  1. public synchronized void load() throws ServletException {
  2. instance = loadServlet();
  3. if (!instanceInitialized) {
  4. initServlet(instance);
  5. }
  6. if (isJspServlet) {
  7. StringBuilder oname =
  8. new StringBuilder(MBeanUtils.getDomain(getParent()));
  9. oname.append(":type=JspMonitor,name=");
  10. oname.append(getName());
  11. oname.append(getWebModuleKeyProperties());
  12. try {
  13. jspMonitorON = new ObjectName(oname.toString());
  14. Registry.getRegistry(null, null)
  15. .registerComponent(instance, jspMonitorON, null);
  16. } catch( Exception ex ) {
  17. log.info("Error registering JSP monitoring with jmx " +
  18. instance);
  19. }
  20. }
  21. }

[java] view plaincopyprint?

  1. private synchronized void initServlet(Servlet servlet)throws ServletException {
  2. if (instanceInitialized && !singleThreadModel) return;
  3. // Call the initialization method of this servlet
  4. try {
  5. instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet);
  6. if (Globals.IS_SECURITY_ENABLED) {
  7. Object[] args = new Object[] { (facade) };
  8. SecurityUtil.doAsPrivilege("init", servlet, classType, args);
  9. args = null;
  10. } else {
  11. servlet.init(facade);
  12. }
  13. instanceInitialized = true;
  14. instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet);
  15. } catch (UnavailableException f) {
  16. //handle exception
  17. }
  18. }

实际上是调用了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

时间: 2024-10-16 22:33:10

Tomcat学习之Wrapper的相关文章

Tomcat 学习进阶历程之Tomcat架构与核心类分析

前面的http及socket两部分内容,主要是为了后面看Tomcat源码而学习的一些网络基础.从这章开始,就开始实际深入到Tomcat的'内在'去看一看. 在分析Tomcat的源码之前,准备先看一下Tomcat的架构与一些核心类的简单分析,并简单介绍一下Tomcat是如何处理一次Http请求的.这部分内容有相当一部分来源于网络,在此,感谢原作者的贡献. Tomcat的总体架构 Tomcat的架构关系可以从Tomcat的配置文件server.xml中看到端倪. 从上图中可以看出Tomcat 的心脏

Tomcat学习 HttpConnector和HttpProcessor启动流程和线程交互

一.tomat启动流程 1.启动HttpConnector connector等待连接请求,只负责接受socket请求,具体处理过程交给HttpProcessor处理. tomcat用户只能访问到connector,能设置接受的数据的buffer大小,而不能看见HttpProcessor的处理过程. 2.创建HttpProcessor对象池 创建对象后马上调用start()方法启动processor的线程: private HttpProcessor newProcessor() { HttpP

Tomcat学习之二:tomcat安装、配置及目录文件说明

我们看到tomcat目录/bin文件夹里有个tomcat6w.exe,顾名思义就是tomcat以window方式显示控制台.第1次点击打开它时候,可能会提示:tomcat指定的服务未安装,此时我们可以这样解决它. 打开命令行提示符窗口-> 进入Tomcat安装目录-> 进入bin目录下-> 输入:service.bat install 即可,如图操作,tomcat目录按自己电脑上的来即可 <!--[endif]--> 这样就可以让tomcat以window方式显示控制台.点击

Tomcat学习总结(8)——Tomcat+Nginx集群解决均衡负载及生产环境热部署

近日,为解决生产环境热部署问题,决定在服务器中增加一个tomcat组成集群,利用集群解决热部署问题. 这样既能解决高并发瓶颈问题,又能解决热部署(不影响用户使用的情况下平滑更新生产服务器)问题. 因为项目是前后端分离的,所以本以为成本很低,没想到遇到了一系列的坑,解决了2天才搞定,发现了很多不是集群而是项目本身的问题. 我是同一个服务器下配置tomcat和nginx等,本文主要面向有一定基础的读者,基本配置就不在本文累述了(基础问题可以留言或者发邮件). 0x0_1 服务器环境 服务器: Cen

tomcat学习之HTTP应用

1 概述 tomcat启动的最后时刻,会启用一个ServerSocket,来接收所有的Web请求(其中大多数是浏览器的请求),处理请求后输出响应到客户端,比如浏览器. Tomcat支持http应用层协议,浏览器向tomcat请求资源大多数用的也是http协议. 本文的重点是,通过简单的类来模拟tomcat服务,其中特别需要注意的是示例代码的开发需要遵循HTTP协议. 2 代码展示 2.1 TestSocket服务类 TestSocket类用来模拟tomcat服务,运行他的main方法,可以启动服

Tomcat 学习进阶历程之关闭钩子

使用JAVA的过程中,经常遇到程序启动时初始化一下资源,或生成一下临时文件,程序退出时要清除这些临时文件,或者程序退出时执行一下必要的其他操作.如果程序是通过我们提供的关闭/退出按钮正常退出的,一切还都好处理,但是如果用户直接关闭虚拟机运行的窗口,那一切就会变的比较复杂. 好在java提供了一种优雅的方式去解决这种问题.使得关闭的善后处理的代码能执行.java的关闭钩子能确保总是执行,无论用户如何终止应用程序.除非用户kill,这个是个死穴. 对java而言,虚拟机会对以下几种操作进行关闭: (

Tomcat 学习进阶历程之Tomcat启动过程分析

本节通过跟踪Tomcat的源码来分析Tomcat是如何启动及装配各个组件的.最好下载Tomcat的源码导入到Eclipse,这样方便跟踪.方法可参考: http://www.cnblogs.com/huangfox/archive/2011/10/20/2218970.html 在Tomcat的启动脚本篇,我们分析过,当执行Start.bat文件时,最后实际调用的是BootStrap.java类.如下图: 如上图,实际调用BootStrap,并传递一个名为'start'参数. 在BootStra

Tomcat学习之ClassLoader

Tomcat学习之ClassLoader 2012-09-04 22:19 8993人阅读 评论(4) 收藏 举报  分类: WEB服务器(13)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 类装载器 JDK中提供了3种不同的类加载器:启动类装载器,扩展类装载器和系统类装载器.引导类装载器,用于引导启动Java虚拟机,当执行一个JAVA程序时,就会启动引导类装载器,它是使用本地代码来实现的,会装载%JAVA_HOME%\\jre\lib\rt.jar,它是所有类装载

Tomcat学习笔记(十)

StandardWrapper容器 Context容器包含一个或者多个Wrapper实例,每个Wrapper实例表示一个具体的servlet定义. 方法调用序列 具体过程 (1)连接器创建request和response对象  (2)连接器调用StandardContext实例的invoke()方法  (3)接着,StandardContext实例的invoke方法调用其管道对象的invoke方法.StandardContext中管道对象的基础阀是StandContextValve类的实例,因此