tomcat学习

来源:互联网 发布:黑心食品知乎 编辑:程序博客网 时间:2024/06/04 19:01

 

tomcat学习

来源:http://thinkinmylife.iteye.com/blog/805058

    博客分类:
  • 程序设计
TomcatServletWebApache虚拟机

1.tomcat介绍

2.tomcat结构

3.Connector 组件

4.Container组件

5.tomcat启动过程

6.tomcat处理请求过程

7.WebappLoader

8.Deployer

9.session Manager

10.servlet Manager

11.shutdown

 

 

tomcat介绍

 

Tomcat是Apache Jakarta软件组织的一个子项目,Tomcat是一个JSP/Servlet容器,它是在SUN公司的JSWDK

(Java Server Web Development Kit)基础上发展起来的一个JSP和Servlet规范的标准实现。

Tomcat和IIS、Apache等Web服务器一样,具有处理HTML页面的功能,不过,Tomcat处理静态HTML的能力不

如Apache服务器

 

tomcat结构

 

 

Xml代码 复制代码 收藏代码
  1. <Server port="8005" shutdown="SHUTDOWN" debug="0">  
  2.   <Service name="Tomcat-Standalone">  
  3.     <!-- HTTP/1.1-->  
  4.     <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"  port="8080".....   
  5.     <!--Coyote/JK2-->  
  6.    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"  port="8009".....   
  7.    <Engine name="Standalone" defaultHost="localhost" debug="0">  
  8.       <Logger className="org.apache.catalina.logger.FileLogger" .../>  
  9.       <Realm className="org.apache.catalina.realm.UserDatabaseRealm" .../>  
  10.        .....   
  11.       <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true">       
  12.         <Context path="" docBase="mycontext" debug="0"/>  
  13.         <Context path="/wsota" docBase="wsotaProject" debug="0"/>     
  14.       </Host>  
  15.       <Host name="www.taobao.com"......   
  16.     </Engine>  
  17.   </Service>  
  18.  <Service name=“Tomcat-demo”>….   
  19.  </Service>  
  20. </Server>  

 

各组件基本介绍:

Container:

可以理解为处理某类型请求的容器,处理的方式一般为把处理请求的处理器包装为Valve对象,并按一定顺序放入类型为Pipeline的管道里。  Container里包含一些基础服务,如Loader、Manager和Realm。

包括以下类型:

Engine:

Engine包含Host和Context,接到请求后仍给相应的Host在相应的Context里处理。

Host:

Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名 

当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理 

Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理

Context:

一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成 Context在创建的时候将根据配置文件$CATALINA_HOME/conf/web.xml$WEBAPP_HOME/WEB-INF/web.xml载入Servlet类 

当Context获得请求时,将在自己的映射表(mapping table)中寻找相匹配的Servlet类

Wrapper:

Wrapper是针对每个Servlet的Container,每个Servlet都有相应的Wrapper来管理。

包括以下类型:

Engine:

Engine包含Host和Context,接到请求后仍给相应的Host在相应的Context里处理。

Host:

Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名 

当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理 

Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理

Context:

一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成 Context在创建的时候将根据配置文件$CATALINA_HOME/conf/web.xml$WEBAPP_HOME/WEB-INF/web.xml载入Servlet类 

当Context获得请求时,将在自己的映射表(mapping table)中寻找相匹配的Servlet类

Wrapper:

Wrapper是针对每个Servlet的Container,每个Servlet都有相应的Wrapper来管理。

 

Connector 组件

1.listen port,create socket,get data

2.create a request objects whose class implements the org.apache.catalina.Request interface

3.create a response objects whose class implements the org.apache.catalina.Response interface

---------------------------------------------

Class Implementation of an HTTP/1.1 connector

1)Tomcat4: HttpConnector(简单,定下了整个架构的基调)

2)CoyoteConnector

3)Tomcat5: Connector

httpconnector

 

coyoteconnector

Container组件

Container

类图:

interface:

Java代码 复制代码 收藏代码
  1. 1.public Container getParent();   
  2. 2.public void setParent(Container container);   
  3. 3.public void addChild(Container child);   
  4. 4.public Container[] findChildren();   
  5. 5.public void invoke(Request request, Response response)   
  6.         throws IOException, ServletException;<SPAN style="WHITE-SPACE: normal"> </SPAN>  

例子:

Java代码 复制代码 收藏代码
  1. Ext:   
  2. …   
  3. Wrapper wrapper1 = new StandardWrapper();   
  4. Wrapper wrapper2 = new StandardWrapper();    
  5. Context context = new StandardContext();   
  6. context.addChild(wrapper1);   
  7. context.addChild(wrapper2);   
  8. Host host = new StandardHost();   
  9. host.addChild(context);   
  10. host.setName("localhost");   
  11. host.setAppBase("webapps");   
  12. …  

Pipeline

interface:

Java代码 复制代码 收藏代码
  1. public interface Pipeline {    
  2.  public Valve getBasic();    
  3.  public void setBasic(Valve valve);   
  4.  public void addValve(Valve valve);   
  5.  public Valve[] getValves();    
  6.  public void invoke(Request request, Response response) throws     IOException, ServletException;   
  7.  public void removeValve(Valve valve);   
  8.  }    
  9. public interface Valve {    
  10.  public String getInfo();    
  11.  public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException;   
  12.  }  

pipeline如何工作:

Java代码 复制代码 收藏代码
  1. //1.pipeline value   
  2. public void invokeNext(Request request, Response response)   
  3.             throws IOException, ServletException {   
  4.             int subscript = stage;   
  5.             stage = stage + 1;//index 指针  
  6.             // Invoke the requested Valve for the current request thread  
  7.             if (subscript < valves.length) {   
  8.                 valves[subscript].invoke(request, response, this);//invoke next if has  
  9.             } else if ((subscript == valves.length) && (basic != null)) {   
  10.                 basic.invoke(request, response, this);//last is basic  
  11.             } else {   
  12.             }   
  13.  }   
  14.   
  15. //2.value invoke   
  16. public void invoke(Request request, Response response, ValveContext valveContext)   
  17.         throws IOException, ServletException {   
  18. ….   
  19. // Pass this request on to the next valve in our pipeline  
  20.    valveContext.invokeNext(request, response);   
  21. ……   
  22. }  
    例子:
Java代码 复制代码 收藏代码
  1. Valve valve1 = new HeaderLoggerValve();   
  2.  Valve valve2 = new ClientIPLoggerValve();   
  3. ((Pipeline) context).addValve(valve1);   
  4. ------1.pipeline.addValve(valve1);   
  5.  ((Pipeline) context).addValve(valve2);   
  6. ------2.pipeline.addValve(valve2);   
  7. public StandardContext() {   
  8.         super();   
  9.         pipeline.setBasic(new StandardContextValve());   
  10.         namingResources.setContainer(this);   
  11.     }   
  12. ----- 3.basic value = StandardContextValve()   
  13. Result:   
  14. Value[]:value1,value2   
  15. basicValue: StandardContextValve  

tomcat例子:

Java代码 复制代码 收藏代码
  1. 1. connector组装完request, response…   
  2. connector.getContainer().invoke(request, response);   
  3.   
  4. 2.container的invoke(),如StandardContext   
  5. public void invoke(Request request,     Response response)   
  6. throws IOException, ServletException {   
  7.      pipeline.invoke(request, response);   
  8.  }   
  9.   
  10. 3. HeaderLoggerValve invoke   
  11. public void invoke(Request request, Response    response, ValveContext valveContext)   
  12.     throws IOException, ServletException {   
  13.     // Pass this request on to the next valve in our pipeline  
  14.     valveContext.invokeNext(request, response);   
  15.     System.out.println("Header Logger Valve");   
  16.     …   
  17.   }   
  18. 4. ClientIPLoggerValve invoke   
  19.  public void invoke(Request request, Response response, ValveContext valveContext)   
  20.     throws IOException, ServletException {   
  21.     // Pass this request on to the next valve in our pipeline  
  22.     valveContext.invokeNext(request, response);   
  23.     System.out.println("Client IP Logger Valve");   
  24. …   
  25. }   
  26.   
  27. 5. StandardContextValve invoke   
  28.  public void invoke(Request request,    Response response, ValveContext     valveContext)   
  29.     throws IOException,     ServletException {   
  30.         ….   
  31. response.setContext(context);   
  32. wrapper.invoke(request, response);   
  33. //执行下一个container的任务   
  34. }  
Lifecycle

interface:

Java代码 复制代码 收藏代码
  1. public interface Lifecycle {    
  2.     public static final String START_EVENT = "start";    
  3.     public static final String BEFORE_START_EVENT = "before_start";    
  4.     public static final String AFTER_START_EVENT = "after_start";    
  5.     public static final String STOP_EVENT = "stop";    
  6.     public static final String BEFORE_STOP_EVENT = "before_stop";    
  7.     public static final String AFTER_STOP_EVENT = "after_stop";    
  8.     public void addLifecycleListener(LifecycleListener listener);    
  9.     public LifecycleListener[] findLifecycleListeners();    
  10.     public void removeLifecycleListener(LifecycleListener listener);    
  11.     public void start() throws LifecycleException;    
  12.     public void stop() throws LifecycleException;    
  13.     }  
lifecycle原理:

Tomcat 中组件的生命周期是通过 Lifecycle 接口来控制的,组件只要继承这个接口并实现其中的方法就可以统一被拥有它的组件控制了,这样一层一层的直到一个最高级的组件就可以控制 Tomcat 中所有组件的生命周期,这个最高的组件就是 Server

public abstract class ContainerBase  implements Container, Lifecycle, Pipeline

Lifecycle start&stop:

Java代码 复制代码 收藏代码
  1. <SPAN style="FONT-WEIGHT: normal">->((Lifecycle) connector).start()   
  2. ->((Lifecycle) host).start()   
  3. ->((Lifecycle) context).start()   
  4. ->((Lifecycle) Wrapper).start()   
  5. ->….   
  6. Start Code:   
  7. …… first start self container   
  8. // Start our child containers, if any   
  9.         Container children[] = findChildren();   
  10.         for (int i = 0; i < children.length; i++) {   
  11.             if (children[i] instanceof Lifecycle)   
  12.                 ((Lifecycle) children[i]).start();   
  13.         }</SPAN>  
Java代码 复制代码 收藏代码
  1. <SPAN style="FONT-WEIGHT: normal">Stop:   
  2. ->((Lifecycle) Wrapper). end()   
  3. ->((Lifecycle) context). end()   
  4. ->((Lifecycle) host). end()   
  5. ->((Lifecycle) connector).end()   
  6. ->….   
  7. Stop code:   
  8. // Stop our child containers, if any   
  9.             Container children[] = findChildren();   
  10.             for (int i = 0; i < children.length; i++) {   
  11.                 if (children[i] instanceof Lifecycle)   
  12.                     ((Lifecycle) children[i]).stop();   
  13.             }   
  14. …… end stop self container   
  15. Ext code:   
  16. StandardContext.start()   
  17. StandardContext.stop()</SPAN>  

LifecycleListener

interface and support class:

Java代码 复制代码 收藏代码
  1. <SPAN style="FONT-WEIGHT: normal">public interface LifecycleListener {   
  2. public void lifecycleEvent(LifecycleEvent event);   
  3. }   
  4. public final class LifecycleEvent   
  5.     extends EventObject {   
  6. public LifecycleEvent(Lifecycle lifecycle, String type) {   
  7.         this(lifecycle, type, null);   
  8.     }   
  9. ……   
  10. }   
  11. public final class LifecycleSupport {   
  12. public void addLifecycleListener(LifecycleListener listener)   
  13. public void fireLifecycleEvent(String type, Object data)   
  14. public void removeLifecycleListener(LifecycleListener listener)   
  15. ……   
  16. }</SPAN>  

类图:  

LifecycleListener例子:

Java代码 复制代码 收藏代码
  1. <SPAN style="FONT-WEIGHT: normal">1:init   
  2. Context context = new StandardContext();   
  3. LifecycleListener listener = new ContextConfig();   
  4. ((Lifecycle) context).addLifecycleListener(listener);   
  5. //1.protected LifecycleSupport lifecycle = new LifecycleSupport(this);  
  6. //2. lifecycle.addLifecycleListener(listener);  
  7. 2:start   
  8. StandardContext.start()   
  9. public synchronized void start() throws LifecycleException {   
  10. lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);   
  11. Start ….   
  12.  lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);   
  13. }   
  14. 3:event   
  15. public void fireLifecycleEvent(String type, Object data) {   
  16.         LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);   
  17.         LifecycleListener interested[] = null;   
  18.         synchronized (listeners) {   
  19.             interested = (LifecycleListener[]) listeners.clone();   
  20.         }   
  21.         for (int i = 0; i < interested.length; i++)   
  22.             interested[i].lifecycleEvent(event);   
  23.     }   
  24. 4: ContextConfig. lifecycleEvent   
  25. public void lifecycleEvent(LifecycleEvent event) {   
  26.         // Identify the context we are associated with  
  27.         try {   
  28.             context = (Context) event.getLifecycle();   
  29.             if (context instanceof StandardContext) {   
  30.                 int contextDebug = ((StandardContext) context).getDebug();   
  31.                 if (contextDebug > this.debug)   
  32.                     this.debug = contextDebug;   
  33.             }   
  34.         } catch (ClassCastException e) {   
  35.             log(sm.getString("contextConfig.cce", event.getLifecycle()), e);   
  36.             return;   
  37.         }   
  38.         // Process the event that has occurred  
  39.         if (event.getType().equals(Lifecycle.START_EVENT))   
  40.             start();   
  41.         else if (event.getType().equals(Lifecycle.STOP_EVENT))   
  42.             stop();   
  43.     }</SPAN>  

tomcat处理请求过程

基本过程:

官方:requestProcess.pdf 

tomcat启动过程

见:serverStartup.pdf

WebappLoader

1.tomcatLoader体系

Tomcat Server的ClassLoader结构如下:


Bootstrap

   |

System

   |

Common

/    \    

Catalina  Shared

     / \

Webapp1   Webapp2 ...


其中:
- Bootstrap - 载入JVM自带的类和$JAVA_HOME/jre/lib/ext/*.jar
- System - 载入$CLASSPATH/*.class,$CATALINA_HOME/bin/bootstrap.jar.
..

- Common - 载入$CATALINA_HOME/common/...,它们对TOMCAT和所有的WEB APP都可见
- Catalina - 载入$CATALINA_HOME/server/...,它们仅对TOMCAT可见,对所有的WEB APP都不可见
- Shared - 载入$CATALINA_HOME/shared/...,它们仅对所有WEB APP可见,对TOMCAT不可见(也不必见)
- WebApp - 载入ContextBase/WEB-INF/classes...,ContextBase/WEB-INF/lib;它们仅对该WEB APP可见

 

 

ClassLoader被组织成树形,一般的工作原理是:
1) 线程需要用到某个类,于是contextClassLoader被请求来载入该类
2) contextClassLoader请求它的父ClassLoader来完成该载入请求
3) 如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入

4) 都无法载入,报classNotFund

但是WebAppClassLoader的工作原理和上述有少许不同:

它先试图自己载入类,如果无法载入,再请求父ClassLoader完成

(自己的载入的类从下面目录拿:ContextBase/WEB-INF/classes,ContextBase/WEB-INF/lib)

 

2.ClassLoader代码

创建3个loader,并且建立父子关系:

 

Java代码 复制代码 收藏代码
  1. unpacked[0] = new File("D:\\ppt\\apache-tomcat-5.5.20\\apache-tomcat-5.5.20\\common\\classes");   
  2. packed2[0] = new File("D:\\ppt\\apache-tomcat-5.5.20\\apache-tomcat-5.5.20\\common\\endorsed");   
  3. packed2[1] = new File("D:\\ppt\\apache-tomcat-5.5.20\\apache-tomcat-5.5.20\\common\\lib");  
Java代码 复制代码 收藏代码
  1. ClassLoader commonLoader = null;   
  2. ClassLoader catalinaLoader = null;   
  3. ClassLoader sharedLoader = null;   
  4. commonLoader =   
  5.                 ClassLoaderFactory.createClassLoader(unpacked, packed2, null);   
  6. catalinaLoader =   
  7.                 ClassLoaderFactory.createClassLoader(unpacked, packed,   
  8.                                                      commonLoader);   
  9. sharedLoader =   
  10.                 ClassLoaderFactory.createClassLoader(unpacked, packed,   
  11.                                                      commonLoader);  

 createLoader实现代码,可以看见tomcat中Loader都是StandardLoader,但是WebappLoader并不是,因为两者的类加载机制不同:

 

 

Java代码 复制代码 收藏代码
  1. classLoader = new StandardClassLoader(array, parent);   
  2.   
  3. public class StandardClassLoader extends URLClassLoader   
  4.     implements Reloader    
  5.   
  6.  public StandardClassLoader(String repositories[]) {   
  7.   
  8.         super(convert(repositories));   
  9.         this.parent = getParent();//父类  
  10.         this.system = getSystemClassLoader();//system  
  11.         securityManager = System.getSecurityManager();   
  12.         if (repositories != null) {   
  13.             for (int i = 0; i < repositories.length; i++)   
  14.                 addRepositoryInternal(repositories[i]);   
  15.         }   
  16.   
  17.     }  

 

WebappLoader与sharedLoader 关系如何建立?

 

Java代码 复制代码 收藏代码
  1. Class startupClass = catalinaLoader.loadClass   
  2.                 ("org.apache.catalina.startup.Catalina");   
  3. Object startupInstance = startupClass.newInstance();   
  4.   
  5. String methodName = "setParentClassLoader";   
  6. Class paramTypes[] = new Class[1];   
  7. paramTypes[0] = Class.forName("java.lang.ClassLoader");   
  8. Object paramValues[] = new Object[1];   
  9. paramValues[0] = sharedLoader;//定义parent  
  10. Method method =   
  11.      startupInstance.getClass().getMethod(methodName, paramTypes);   
  12. method.invoke(startupInstance, paramValues);  

 

 说明:systemLoader创建完3个loader后,马上将classLoader切换至catalinaLoader,

catalinaLoader将负责加载tomcat的组件类,Catalina,standardServer,standardContext,包括WebappLoader;

但是webappLoader初始化ok后,去Load应用的时候,将自己去加载,加载不了由父加载器加载,而父亲加载器就是上述组件的父加载器:sharedLoader

 

  3.WebappLoader

 

 

webappLoader代码:

 

Java代码 复制代码 收藏代码
  1. public class WebappLoader   
  2.     implements Lifecycle, Loader, PropertyChangeListener, Runnable   
  3.   
  4. public WebappLoader(ClassLoader parent) {   
  5.         super();   
  6.         this.parentClassLoader = parent;//parent is sharedLoader  
  7.   
  8.     }   
  9.   
  10. //创建WebAppclassLoader   
  11. classLoader = createClassLoader();   
  12. classLoader.setResources(container.getResources());   
  13.   
  14. //loaderClass:   
  15. //String loaderClass =   
  16.         "org.apache.catalina.loader.WebappClassLoader";   
  17.   
  18. private WebappClassLoader createClassLoader()   
  19.         throws Exception {   
  20.   
  21.         Class clazz = Class.forName(loaderClass);   
  22.         WebappClassLoader classLoader = null;   
  23.   
  24.         if (parentClassLoader == null) {   
  25.             // Will cause a ClassCast is the class does not extend WCL, but  
  26.             // this is on purpose (the exception will be caught and rethrown)  
  27.             classLoader = (WebappClassLoader) clazz.newInstance();   
  28.         } else {   
  29.             Class[] argTypes = { ClassLoader.class };   
  30.             Object[] args = { parentClassLoader };   
  31.             Constructor constr = clazz.getConstructor(argTypes);   
  32.             classLoader = (WebappClassLoader) constr.newInstance(args);   
  33.         }   
  34.         return classLoader;   
  35.     }  

 4.ClassLoader和WebappLoader协作

如何更改当前线程的classloader:


Java代码 复制代码 收藏代码
  1. Thread.currentThread().setContextClassLoader(catalinaLoader);  

 

 

5.WebappClassLoader加载servlet class

 

1.tomcat之前是否已经加载缓存过,如果加载过的话,直接返回,如servletClass;

 

Java代码 复制代码 收藏代码
  1. ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);  

 

2.查看该classLoader之前是否在家,jvm中有缓存class,如果有直接返回class;

3.用systemLoader去加载,如果J2SE。J2EE的jar包,此时可以直接加载返回;

4.到这里加载还不能成功,需要用securityManager来判断是否可以记载;

5.没办法,webappclassLoader来加载吧,如servlet class;

6.还不行,交parentClassLoader来记载,shareClassLoader;加载不到,返回CNE;

Deployer

1.deployer interface

 

 

Java代码 复制代码 收藏代码
  1. public interface Deployer  {   
  2.        
  3.     public static final String PRE_INSTALL_EVENT = "pre-install";   
  4.     public static final String INSTALL_EVENT = "install";   
  5.     public static final String REMOVE_EVENT = "remove";   
  6.   
  7.   
  8.     // --------------------------------------------------------- Public Methods  
  9.   
  10.     public String getName();   
  11.      //部署   
  12.     public void install(String contextPath, URL war) throws IOException;   
  13.      //部署   
  14.     public void install(URL config, URL war) throws IOException;   
  15.     public Context findDeployedApp(String contextPath);   
  16.     public String[] findDeployedApps();   
  17.     public void remove(String contextPath) throws IOException;   
  18.     public void start(String contextPath) throws IOException;   
  19.     public void stop(String contextPath) throws IOException;   
  20.   
  21.   
  22. }  
 

a:会把2个目录里面部署:

1。webapps

2。server/webapps

webapps部署自定义的应用,以war包,文件等形式;server/webapps部署后台管理应用,serlvetManager和hostManager。

b:部署的核心

部署的核心都是从web.xml开始,定位到应用目录后,开始解析web.xml文件,实例化出servlet,filter及各种变量等。除了解析应用的web.xml,tomcat自带默认的web.xml,目录conf/web.xml,创建出常用的3个serlvet:DefaultServlet,InvokerServlet,JspServlet

DefaultServlet:无法映射到servlet的请求,全部由它处理

InvokerServlet:未在web.xml的servlet,通过/servlet/*来访问

JspServlet:处理*.jsp

 

Java代码 复制代码 收藏代码
  1. public static void main(String[] args) {   
  2.     System.setProperty("catalina.base", System.getProperty("user.dir"));   
  3.     Connector connector = new HttpConnector();   
  4.     //Context   
  5.     Context context = new StandardContext();   
  6.     LifecycleListener listener = new ContextConfig();   
  7.     ((Lifecycle) context).addLifecycleListener(listener);   
  8.     //Host   
  9.     Host host = new StandardHost();   
  10.     host.addChild(context);   
  11.     host.setName("localhost");   
  12.     host.setAppBase("webapps");   
  13.     LifecycleListener listener2 = new HostConfig();   
  14.     ((Lifecycle) host).addLifecycleListener(listener2);   
  15.     //engine   
  16.     Engine engine = new StandardEngine();   
  17.     engine.addChild(host);   
  18.     engine.setName("localhost");   
  19.     Mapper mapper = new StandardEngineMapper();   
  20.     mapper.setProtocol("http");   
  21.     engine.addMapper(mapper);   
  22.        
  23.     Loader loader = new WebappLoader();   
  24.     context.setLoader(loader);   
  25.     connector.setContainer(engine);   
  26.     try {   
  27.       connector.initialize();   
  28.       ((Lifecycle) connector).start();   
  29.       ((Lifecycle) host).start();   
  30.       Container[] c = context.findChildren();   
  31.       int length = c.length;   
  32.       for (int i=0; i<length; i++) {   
  33.         Container child = c[i];   
  34.         System.out.println(child.getName());   
  35.       }   
  36.       System.in.read();   
  37.       ((Lifecycle) host).stop();   
  38.     }   
  39.     catch (Exception e) {   
  40.       e.printStackTrace();   
  41.     }   
  42.   }  
 

 2.HostConfig

 

  3.contextConfig

 

 

Session Manager

1.session

StandardSession包含大量底层方法,不适合暴露给给servlet,采用装饰模式给封装下:StandardSessionFacade

只包含javax.servlet.http.HttpSession方法

 

 

Java代码 复制代码 收藏代码
  1. public HttpSession getSession() {   
  2.   
  3.         if (facade == null)   
  4.             facade = new StandardSessionFacade(this);   
  5.         return (facade);   
  6.   
  7.     }  
 

2.manager

 

 

Java代码 复制代码 收藏代码
  1. public interface Manager {   
  2.  public Container getContainer();   
  3.  public void setContainer(Container container);   
  4.  public DefaultContext getDefaultContext();   
  5.  public void setDefaultContext(DefaultContext defaultContext);   
  6.  public boolean getDistributable();   
  7.  public void setDistributable(boolean distributable);   
  8.  public String getInfo();   
  9.  public int getMaxInactiveInterval();   
  10.  public void setMaxInactiveInterval(int interval);   
  11.  public void add(Session session);   
  12.  public void addPropertyChangeListener(PropertyChangeListener listener);   
  13. //创建一个session   
  14.  public Session createSession();   
  15. //map里面查找session   
  16.  public Session findSession(String id) throws IOException;   
  17.  public Session[] findSessions();   
  18. //启动的时候,从本地文件加载已有的session   
  19.  public void load() throws ClassNotFoundException, IOException;   
  20. //移除一个session   
  21.   public void remove(Session session);   
  22.   public void removePropertyChangeListener(PropertyChangeListener listener);   
  23. //tomcat关闭,还存活的session序列化入本地文件   
  24.  public void unload() throws IOException;    
  25. }  

 StandardManager启用一个map来维护session:

 

Java代码 复制代码 收藏代码
  1. protected HashMap sessions = new HashMap();  

 所有session存放在内存中,都有一个最大存活时间,默认是60s;后台一个线程轮训监控着,超时的session将会销毁并回收。对于session的获取,也只需从map里面get即可。

PersistentManagerBase也是用map来维护session;但是相对standardManager来说,session的管理稍微复杂,对于超时的会销毁;同时若session同时存活数很大的话或者某些比较老的session,支持序列化到硬盘文件和数据库,释放内存压力;但同时session的获取会比较麻烦,map去完,还得硬盘文件中查找,并反序列化为对象。

 

 

3.session的获取,保存

 

4.session的生命周期管理

 

5.session的存储方式

以文件存储为例:

 

 

Servlet Manager

1.后台应用manager

../server/webapps/manager 

server目录下面部署着后台程序manager应用

webapps目录下面有manager.xml

 

Xml代码 复制代码 收藏代码
  1. <Context path="/manager" docBase="../server/webapps/manager"  
  2.         debug="0" privileged="true">  
  3.   
  4.   <!-- Link to the user database we will get roles from -->  
  5.   <ResourceLink name="users" global="UserDatabase"  
  6.                 type="org.apache.catalina.UserDatabase"/>  
  7.   
  8. </Context>  

tomcat部署时,该应用也会部署。

 

manager应用的web.xml:

 

Xml代码 复制代码 收藏代码
  1. <servlet>  
  2.   <servlet-name>Manager</servlet-name>  
  3.   <servlet-class>org.apache.catalina.servlets.ManagerServlet</servlet-class>  
  4.   <init-param>  
  5.     <param-name>debug</param-name>  
  6.     <param-value>2</param-value>  
  7.   </init-param>  
  8. </servlet>  
  9. <servlet>  
  10.   <servlet-name>HTMLManager</servlet-name>  
  11.   <servlet-class>org.apache.catalina.servlets.HTMLManagerServlet</servlet-class>  
  12.   <init-param>  
  13.     <param-name>debug</param-name>  
  14.     <param-value>2</param-value>  
  15.   </init-param>  
  16. </servlet>  

2.管理类ManagerServlet

管理serlvet和html,看下ManagerServlet:

 

接口ContainerSerlvet

 

Java代码 复制代码 收藏代码
  1. public interface ContainerServlet {   
  2.   
  3.     // ------------------------------------------------------------- Properties  
  4.   
  5.     /**  
  6.      * Return the Wrapper with which this Servlet is associated. 
  7.      */  
  8.     public Wrapper getWrapper();   
  9.   
  10.     /**  
  11.      * Set the Wrapper with which this Servlet is associated. 
  12.      *  
  13.      * @param wrapper The new associated Wrapper  
  14.      */  
  15.     public void setWrapper(Wrapper wrapper);   
  16.   
  17. }  

 

 类ManagerServlet:

 

Java代码 复制代码 收藏代码
  1. public class ManagerServlet   
  2.     extends HttpServlet implements ContainerServlet {   
  3.   
  4. //....忽略   
  5.   
  6.  public void doGet(HttpServletRequest request,   
  7.                       HttpServletResponse response)   
  8.         throws IOException, ServletException {   
  9.        //...乎略   
  10.        if (command == null) {   
  11.             writer.println(sm.getString("managerServlet.noCommand"));   
  12.         } else if (command.equals("/install")) {   
  13.             install(writer, config, path, war);   
  14.         } else if (command.equals("/list")) {   
  15.             list(writer);   
  16.         } else if (command.equals("/reload")) {   
  17.             reload(writer, path);   
  18.         } else if (command.equals("/remove")) {   
  19.             remove(writer, path);   
  20.         } else if (command.equals("/resources")) {   
  21.             resources(writer, type);   
  22.         } else if (command.equals("/roles")) {   
  23.             roles(writer);   
  24.         } else if (command.equals("/sessions")) {   
  25.             sessions(writer, path);   
  26.         } else if (command.equals("/start")) {   
  27.             start(writer, path);   
  28.         } else if (command.equals("/stop")) {   
  29.             stop(writer, path);   
  30.         } else if (command.equals("/undeploy")) {   
  31.             undeploy(writer, path);   
  32.         } else {   
  33.                      writer.println(sm.getString("managerServlet.unknownCommand",   
  34.                                         command));   
  35.         }   
  36.   
  37.  }   
  38.   
  39. //.....忽略   
  40.   
  41. }  
 

   比如启动应用:

 

Java代码 复制代码 收藏代码
  1. protected void start(PrintWriter writer, String path) {   
  2.   
  3.         if (debug >= 1)   
  4.             log("start: Starting web application at '" + path + "'");   
  5.   
  6.         if ((path == null) || (!path.startsWith("/") && path.equals(""))) {   
  7.             writer.println(sm.getString("managerServlet.invalidPath", path));   
  8.             return;   
  9.         }   
  10.         String displayPath = path;   
  11.         if( path.equals("/") )   
  12.             path = "";   
  13.   
  14.         try {   
  15.             //找到需要启动的应用   
  16.             Context context = deployer.findDeployedApp(path);   
  17.             if (context == null) {   
  18.                 writer.println(sm.getString("managerServlet.noContext", displayPath));   
  19.                 return;   
  20.             }   
  21.             //应用启动   
  22.             deployer.start(path);   
  23.             if (context.getAvailable())   
  24.                 writer.println   
  25.                     (sm.getString("managerServlet.started", displayPath));   
  26.             else  
  27.                 writer.println   
  28.                     (sm.getString("managerServlet.startFailed", displayPath));   
  29.         } catch (Throwable t) {   
  30.             getServletContext().log   
  31.                 (sm.getString("managerServlet.startFailed", displayPath), t);   
  32.             writer.println   
  33.                 (sm.getString("managerServlet.startFailed", displayPath));   
  34.             writer.println(sm.getString("managerServlet.exception",   
  35.                                         t.toString()));   
  36.         }   
  37.   
  38.     }  
 

ShutDown

1.Runtime

Runtime类封装了运行时的环境。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。      

一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用。      

一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。        

 

addShutdownHook(Thread hook) :注册新的虚拟机来关闭挂钩。      

availableProcessors() :向 Java 虚拟机返回可用处理器的数目。    

exec(String command) :在单独的进程中执行指定的字符串命令。

gc() :运行垃圾回收器

getRuntime() :返回与当前 Java 应用程序相关的运行时对象。

removeShutdownHook(Thread hook)  :取消注册某个先前已注册的虚拟机关闭挂钩。 

。。。

2.tomcat的ShutdownHook

 

Java代码 复制代码 收藏代码
  1. /**  
  2.     * Shutdown hook which will perform a clean shutdown of Catalina if needed. 
  3.     */  
  4.    protected class CatalinaShutdownHook extends Thread {   
  5.   
  6.        public void run() {   
  7.   
  8.            if (server != null) {   
  9.                try {   
  10.                    ((Lifecycle) server).stop();   
  11.                } catch (LifecycleException e) {   
  12.                    System.out.println("Catalina.stop: " + e);   
  13.                    e.printStackTrace(System.out);   
  14.                    if (e.getThrowable() != null) {   
  15.                        System.out.println("----- Root Cause -----");   
  16.                        e.getThrowable().printStackTrace(System.out);   
  17.                    }   
  18.                }   
  19.            }   
  20.   
  21.        }   
  22.    }  
 

server start:

 

Java代码 复制代码 收藏代码
  1. Thread shutdownHook = new CatalinaShutdownHook();   
  2.   
  3.         // Start the new server   
  4.         if (server instanceof Lifecycle) {   
  5.             try {   
  6.                 server.initialize();   
  7.                 ((Lifecycle) server).start();   
  8.                 try {   
  9.                     // Register shutdown hook  
  10.                     //look here   
  11.                     Runtime.getRuntime().addShutdownHook(shutdownHook);   
  12.                 } catch (Throwable t) {   
  13.                     // This will fail on JDK 1.2. Ignoring, as Tomcat can run  
  14.                     // fine without the shutdown hook.  
  15.                 }   
  16.                 // Wait for the server to be told to shut down  
  17.                 server.await();   
  18.             } catch (LifecycleException e) {   
  19.                 System.out.println("Catalina.start: " + e);   
  20.                 e.printStackTrace(System.out);   
  21.                 if (e.getThrowable() != null) {   
  22.                     System.out.println("----- Root Cause -----");   
  23.                     e.getThrowable().printStackTrace(System.out);   
  24.                 }   
  25.             }   
  26.         }  
 

server stop:

 

Java代码 复制代码 收藏代码
  1. // Shut down the server   
  2.         if (server instanceof Lifecycle) {   
  3.             try {   
  4.                 try {   
  5.                     // Remove the ShutdownHook first so that server.stop()  
  6.                     // doesn't get invoked twice  
  7.                     Runtime.getRuntime().removeShutdownHook(shutdownHook);   
  8.                 } catch (Throwable t) {   
  9.                     // This will fail on JDK 1.2. Ignoring, as Tomcat can run  
  10.                     // fine without the shutdown hook.  
  11.                 }   
  12.                 ((Lifecycle) server).stop();   
  13.             } catch (LifecycleException e) {   
  14.                 System.out.println("Catalina.stop: " + e);   
  15.                 e.printStackTrace(System.out);   
  16.                 if (e.getThrowable() != null) {   
  17.                     System.out.println("----- Root Cause -----");   
  18.                     e.getThrowable().printStackTrace(System.out);   
  19.                 }   
  20.             }   
  21.         }  
 
0 0