`
ThinkInMyLife
  • 浏览: 48773 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

tomcat学习

阅读更多

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结构

 

 

<Server port="8005" shutdown="SHUTDOWN" debug="0">
  <Service name="Tomcat-Standalone">
    <!-- HTTP/1.1-->
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"  port="8080".....
    <!--Coyote/JK2-->
   <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"  port="8009".....
   <Engine name="Standalone" defaultHost="localhost" debug="0">
      <Logger className="org.apache.catalina.logger.FileLogger" .../>
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm" .../>
       .....
      <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true">    
        <Context path="" docBase="mycontext" debug="0"/>
        <Context path="/wsota" docBase="wsotaProject" debug="0"/>  
      </Host>
      <Host name="www.taobao.com"......
    </Engine>
  </Service>
 <Service name=“Tomcat-demo”>….
 </Service>
</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:

1.public Container getParent();
2.public void setParent(Container container);
3.public void addChild(Container child);
4.public Container[] findChildren();
5.public void invoke(Request request, Response response)
        throws IOException, ServletException; 

例子:

Ext:
…
Wrapper wrapper1 = new StandardWrapper();
Wrapper wrapper2 = new StandardWrapper(); 
Context context = new StandardContext();
context.addChild(wrapper1);
context.addChild(wrapper2);
Host host = new StandardHost();
host.addChild(context);
host.setName("localhost");
host.setAppBase("webapps");
…

Pipeline

interface:

public interface Pipeline { 
 public Valve getBasic(); 
 public void setBasic(Valve valve);
 public void addValve(Valve valve);
 public Valve[] getValves(); 
 public void invoke(Request request, Response response) throws     IOException, ServletException;
 public void removeValve(Valve valve);
 } 
public interface Valve { 
 public String getInfo(); 
 public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException;
 }

pipeline如何工作:

//1.pipeline value
public void invokeNext(Request request, Response response)
           	throws IOException, ServletException {
            int subscript = stage;
            stage = stage + 1;//index 指针
            // Invoke the requested Valve for the current request thread
            if (subscript < valves.length) {
                valves[subscript].invoke(request, response, this);//invoke next if has
            } else if ((subscript == valves.length) && (basic != null)) {
                basic.invoke(request, response, this);//last is basic
            } else {
            }
 }

//2.value invoke
public void invoke(Request request, Response response, ValveContext valveContext)
    	throws IOException, ServletException {
….
// Pass this request on to the next valve in our pipeline
   valveContext.invokeNext(request, response);
……
}
    例子:
Valve valve1 = new HeaderLoggerValve();
 Valve valve2 = new ClientIPLoggerValve();
((Pipeline) context).addValve(valve1);
------1.pipeline.addValve(valve1);
 ((Pipeline) context).addValve(valve2);
------2.pipeline.addValve(valve2);
public StandardContext() {
        super();
        pipeline.setBasic(new StandardContextValve());
        namingResources.setContainer(this);
    }
----- 3.basic value = StandardContextValve()
Result:
Value[]:value1,value2
basicValue: StandardContextValve

tomcat例子:

1. connector组装完request, response…
connector.getContainer().invoke(request, response);

2.container的invoke(),如StandardContext
public void invoke(Request request, 	Response response)
throws IOException, ServletException {
     pipeline.invoke(request, response);
 }

3. HeaderLoggerValve invoke
public void invoke(Request request, Response 	response, ValveContext valveContext)
    throws IOException, ServletException {
    // Pass this request on to the next valve in our pipeline
    valveContext.invokeNext(request, response);
    System.out.println("Header Logger Valve");
    …
  }
4. ClientIPLoggerValve invoke
 public void invoke(Request request, Response response, ValveContext valveContext)
    throws IOException, ServletException {
    // Pass this request on to the next valve in our pipeline
    valveContext.invokeNext(request, response);
    System.out.println("Client IP Logger Valve");
…
}

5. StandardContextValve invoke
 public void invoke(Request request, 	Response response, ValveContext 	valveContext)
    throws IOException, 	ServletException {
		….
response.setContext(context);
wrapper.invoke(request, response);
//执行下一个container的任务
}
Lifecycle

interface:

public interface Lifecycle { 
    public static final String START_EVENT = "start"; 
    public static final String BEFORE_START_EVENT = "before_start"; 
    public static final String AFTER_START_EVENT = "after_start"; 
    public static final String STOP_EVENT = "stop"; 
    public static final String BEFORE_STOP_EVENT = "before_stop"; 
    public static final String AFTER_STOP_EVENT = "after_stop"; 
    public void addLifecycleListener(LifecycleListener listener); 
    public LifecycleListener[] findLifecycleListeners(); 
    public void removeLifecycleListener(LifecycleListener listener); 
    public void start() throws LifecycleException; 
    public void stop() throws LifecycleException; 
	}
lifecycle原理:

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

public abstract class ContainerBase  implements Container, Lifecycle, Pipeline

Lifecycle start&stop:

->((Lifecycle) connector).start()
->((Lifecycle) host).start()
->((Lifecycle) context).start()
->((Lifecycle) Wrapper).start()
->….
Start Code:
…… first start self container
// Start our child containers, if any
        Container children[] = findChildren();
        for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof Lifecycle)
                ((Lifecycle) children[i]).start();
        }
Stop:
->((Lifecycle) Wrapper). end()
->((Lifecycle) context). end()
->((Lifecycle) host). end()
->((Lifecycle) connector).end()
->….
Stop code:
// Stop our child containers, if any
            Container children[] = findChildren();
            for (int i = 0; i < children.length; i++) {
                if (children[i] instanceof Lifecycle)
                    ((Lifecycle) children[i]).stop();
            }
…… end stop self container
Ext code:
StandardContext.start()
StandardContext.stop()

LifecycleListener

interface and support class:

public interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}
public final class LifecycleEvent
    extends EventObject {
public LifecycleEvent(Lifecycle lifecycle, String type) {
        this(lifecycle, type, null);
    }
……
}
public final class LifecycleSupport {
public void addLifecycleListener(LifecycleListener listener)
public void fireLifecycleEvent(String type, Object data)
public void removeLifecycleListener(LifecycleListener listener)
……
}

类图:  

LifecycleListener例子:

1:init
Context context = new StandardContext();
LifecycleListener listener = new ContextConfig();
((Lifecycle) context).addLifecycleListener(listener);
//1.protected LifecycleSupport lifecycle = new LifecycleSupport(this);
//2. lifecycle.addLifecycleListener(listener);
2:start
StandardContext.start()
public synchronized void start() throws LifecycleException {
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
Start ….
 lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
3:event
public void fireLifecycleEvent(String type, Object data) {
        LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
        LifecycleListener interested[] = null;
        synchronized (listeners) {
            interested = (LifecycleListener[]) listeners.clone();
        }
        for (int i = 0; i < interested.length; i++)
            interested[i].lifecycleEvent(event);
    }
4: ContextConfig. lifecycleEvent
public void lifecycleEvent(LifecycleEvent event) {
        // Identify the context we are associated with
        try {
            context = (Context) event.getLifecycle();
            if (context instanceof StandardContext) {
                int contextDebug = ((StandardContext) context).getDebug();
                if (contextDebug > this.debug)
                    this.debug = contextDebug;
            }
        } catch (ClassCastException e) {
            log(sm.getString("contextConfig.cce", event.getLifecycle()), e);
            return;
        }
        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.START_EVENT))
            start();
        else if (event.getType().equals(Lifecycle.STOP_EVENT))
            stop();
    }

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,并且建立父子关系:

 

 unpacked[0] = new File("D:\\ppt\\apache-tomcat-5.5.20\\apache-tomcat-5.5.20\\common\\classes");
 packed2[0] = new File("D:\\ppt\\apache-tomcat-5.5.20\\apache-tomcat-5.5.20\\common\\endorsed");
 packed2[1] = new File("D:\\ppt\\apache-tomcat-5.5.20\\apache-tomcat-5.5.20\\common\\lib");
ClassLoader commonLoader = null;
ClassLoader catalinaLoader = null;
ClassLoader sharedLoader = null;
commonLoader =
                ClassLoaderFactory.createClassLoader(unpacked, packed2, null);
catalinaLoader =
                ClassLoaderFactory.createClassLoader(unpacked, packed,
                                                     commonLoader);
sharedLoader =
                ClassLoaderFactory.createClassLoader(unpacked, packed,
                                                     commonLoader);

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

 

 

classLoader = new StandardClassLoader(array, parent);

public class StandardClassLoader extends URLClassLoader
    implements Reloader 

 public StandardClassLoader(String repositories[]) {

        super(convert(repositories));
        this.parent = getParent();//父类
        this.system = getSystemClassLoader();//system
        securityManager = System.getSecurityManager();
        if (repositories != null) {
            for (int i = 0; i < repositories.length; i++)
                addRepositoryInternal(repositories[i]);
        }

    }

 

WebappLoader与sharedLoader 关系如何建立?

 

Class startupClass = catalinaLoader.loadClass
                ("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();

String methodName = "setParentClassLoader";
Class paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;//定义parent
Method method =
     startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);

 

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

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

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

 

  3.WebappLoader

 

 

webappLoader代码:

 

public class WebappLoader
    implements Lifecycle, Loader, PropertyChangeListener, Runnable

public WebappLoader(ClassLoader parent) {
        super();
        this.parentClassLoader = parent;//parent is sharedLoader

    }

//创建WebAppclassLoader
classLoader = createClassLoader();
classLoader.setResources(container.getResources());

//loaderClass:
//String loaderClass =
        "org.apache.catalina.loader.WebappClassLoader";

private WebappClassLoader createClassLoader()
        throws Exception {

        Class clazz = Class.forName(loaderClass);
        WebappClassLoader classLoader = null;

        if (parentClassLoader == null) {
            // Will cause a ClassCast is the class does not extend WCL, but
            // this is on purpose (the exception will be caught and rethrown)
            classLoader = (WebappClassLoader) clazz.newInstance();
        } else {
            Class[] argTypes = { ClassLoader.class };
            Object[] args = { parentClassLoader };
            Constructor constr = clazz.getConstructor(argTypes);
            classLoader = (WebappClassLoader) constr.newInstance(args);
        }
        return classLoader;
    }

 4.ClassLoader和WebappLoader协作

如何更改当前线程的classloader:


Thread.currentThread().setContextClassLoader(catalinaLoader);

 

 

5.WebappClassLoader加载servlet class

 

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

 

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

 

 

public interface Deployer  {
    
    public static final String PRE_INSTALL_EVENT = "pre-install";
    public static final String INSTALL_EVENT = "install";
    public static final String REMOVE_EVENT = "remove";


    // --------------------------------------------------------- Public Methods

    public String getName();
     //部署
    public void install(String contextPath, URL war) throws IOException;
     //部署
    public void install(URL config, URL war) throws IOException;
    public Context findDeployedApp(String contextPath);
    public String[] findDeployedApps();
    public void remove(String contextPath) throws IOException;
    public void start(String contextPath) throws IOException;
    public void stop(String contextPath) throws IOException;


}
 

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

 

public static void main(String[] args) {
    System.setProperty("catalina.base", System.getProperty("user.dir"));
    Connector connector = new HttpConnector();
    //Context
    Context context = new StandardContext();
    LifecycleListener listener = new ContextConfig();
    ((Lifecycle) context).addLifecycleListener(listener);
    //Host
    Host host = new StandardHost();
    host.addChild(context);
    host.setName("localhost");
    host.setAppBase("webapps");
    LifecycleListener listener2 = new HostConfig();
    ((Lifecycle) host).addLifecycleListener(listener2);
    //engine
    Engine engine = new StandardEngine();
    engine.addChild(host);
    engine.setName("localhost");
    Mapper mapper = new StandardEngineMapper();
    mapper.setProtocol("http");
    engine.addMapper(mapper);
    
    Loader loader = new WebappLoader();
    context.setLoader(loader);
    connector.setContainer(engine);
    try {
      connector.initialize();
      ((Lifecycle) connector).start();
      ((Lifecycle) host).start();
      Container[] c = context.findChildren();
      int length = c.length;
      for (int i=0; i<length; i++) {
        Container child = c[i];
        System.out.println(child.getName());
      }
      System.in.read();
      ((Lifecycle) host).stop();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
 

 2.HostConfig

 

  3.contextConfig

 

 

Session Manager

1.session

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

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

 

 

public HttpSession getSession() {

        if (facade == null)
            facade = new StandardSessionFacade(this);
        return (facade);

    }
 

2.manager

 

 

public interface Manager {
 public Container getContainer();
 public void setContainer(Container container);
 public DefaultContext getDefaultContext();
 public void setDefaultContext(DefaultContext defaultContext);
 public boolean getDistributable();
 public void setDistributable(boolean distributable);
 public String getInfo();
 public int getMaxInactiveInterval();
 public void setMaxInactiveInterval(int interval);
 public void add(Session session);
 public void addPropertyChangeListener(PropertyChangeListener listener);
//创建一个session
 public Session createSession();
//map里面查找session
 public Session findSession(String id) throws IOException;
 public Session[] findSessions();
//启动的时候,从本地文件加载已有的session
 public void load() throws ClassNotFoundException, IOException;
//移除一个session
  public void remove(Session session);
  public void removePropertyChangeListener(PropertyChangeListener listener);
//tomcat关闭,还存活的session序列化入本地文件
 public void unload() throws IOException; 
}

 StandardManager启用一个map来维护session:

 

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

 

<Context path="/manager" docBase="../server/webapps/manager"
        debug="0" privileged="true">

  <!-- Link to the user database we will get roles from -->
  <ResourceLink name="users" global="UserDatabase"
                type="org.apache.catalina.UserDatabase"/>

</Context>

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

 

manager应用的web.xml:

 

  <servlet>
    <servlet-name>Manager</servlet-name>
    <servlet-class>org.apache.catalina.servlets.ManagerServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
    </init-param>
  </servlet>
  <servlet>
    <servlet-name>HTMLManager</servlet-name>
    <servlet-class>org.apache.catalina.servlets.HTMLManagerServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
    </init-param>
  </servlet>

2.管理类ManagerServlet

管理serlvet和html,看下ManagerServlet:

 

接口ContainerSerlvet

 

public interface ContainerServlet {

    // ------------------------------------------------------------- Properties

    /**
     * Return the Wrapper with which this Servlet is associated.
     */
    public Wrapper getWrapper();

    /**
     * Set the Wrapper with which this Servlet is associated.
     *
     * @param wrapper The new associated Wrapper
     */
    public void setWrapper(Wrapper wrapper);

}

 

 类ManagerServlet:

 

public class ManagerServlet
    extends HttpServlet implements ContainerServlet {

//....忽略

 public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException {
       //...乎略
       if (command == null) {
            writer.println(sm.getString("managerServlet.noCommand"));
        } else if (command.equals("/install")) {
            install(writer, config, path, war);
        } else if (command.equals("/list")) {
            list(writer);
        } else if (command.equals("/reload")) {
            reload(writer, path);
        } else if (command.equals("/remove")) {
            remove(writer, path);
        } else if (command.equals("/resources")) {
            resources(writer, type);
        } else if (command.equals("/roles")) {
            roles(writer);
        } else if (command.equals("/sessions")) {
            sessions(writer, path);
        } else if (command.equals("/start")) {
            start(writer, path);
        } else if (command.equals("/stop")) {
            stop(writer, path);
        } else if (command.equals("/undeploy")) {
            undeploy(writer, path);
        } else {
                     writer.println(sm.getString("managerServlet.unknownCommand",
                                        command));
        }

 }

//.....忽略

}
 

   比如启动应用:

 

protected void start(PrintWriter writer, String path) {

        if (debug >= 1)
            log("start: Starting web application at '" + path + "'");

        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            writer.println(sm.getString("managerServlet.invalidPath", path));
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";

        try {
            //找到需要启动的应用
            Context context = deployer.findDeployedApp(path);
            if (context == null) {
                writer.println(sm.getString("managerServlet.noContext", displayPath));
                return;
            }
            //应用启动
            deployer.start(path);
            if (context.getAvailable())
                writer.println
                    (sm.getString("managerServlet.started", displayPath));
            else
                writer.println
                    (sm.getString("managerServlet.startFailed", displayPath));
        } catch (Throwable t) {
            getServletContext().log
                (sm.getString("managerServlet.startFailed", displayPath), t);
            writer.println
                (sm.getString("managerServlet.startFailed", displayPath));
            writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));
        }

    }
 

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

 

 /**
     * Shutdown hook which will perform a clean shutdown of Catalina if needed.
     */
    protected class CatalinaShutdownHook extends Thread {

        public void run() {

            if (server != null) {
                try {
                    ((Lifecycle) server).stop();
                } catch (LifecycleException e) {
                    System.out.println("Catalina.stop: " + e);
                    e.printStackTrace(System.out);
                    if (e.getThrowable() != null) {
                        System.out.println("----- Root Cause -----");
                        e.getThrowable().printStackTrace(System.out);
                    }
                }
            }

        }
    }
 

server start:

 

Thread shutdownHook = new CatalinaShutdownHook();

        // Start the new server
        if (server instanceof Lifecycle) {
            try {
                server.initialize();
                ((Lifecycle) server).start();
                try {
                    // Register shutdown hook
                    //look here
                    Runtime.getRuntime().addShutdownHook(shutdownHook);
                } catch (Throwable t) {
                    // This will fail on JDK 1.2. Ignoring, as Tomcat can run
                    // fine without the shutdown hook.
                }
                // Wait for the server to be told to shut down
                server.await();
            } catch (LifecycleException e) {
                System.out.println("Catalina.start: " + e);
                e.printStackTrace(System.out);
                if (e.getThrowable() != null) {
                    System.out.println("----- Root Cause -----");
                    e.getThrowable().printStackTrace(System.out);
                }
            }
        }
 

server stop:

 

// Shut down the server
        if (server instanceof Lifecycle) {
            try {
                try {
                    // Remove the ShutdownHook first so that server.stop()
                    // doesn't get invoked twice
                    Runtime.getRuntime().removeShutdownHook(shutdownHook);
                } catch (Throwable t) {
                    // This will fail on JDK 1.2. Ignoring, as Tomcat can run
                    // fine without the shutdown hook.
                }
                ((Lifecycle) server).stop();
            } catch (LifecycleException e) {
                System.out.println("Catalina.stop: " + e);
                e.printStackTrace(System.out);
                if (e.getThrowable() != null) {
                    System.out.println("----- Root Cause -----");
                    e.getThrowable().printStackTrace(System.out);
                }
            }
        }
 

后续学习:jsp编译,https,http ssl,tomcat6,7。

 

分享到:
评论

相关推荐

    Tomcat学习资料1

    【标题】:“Tomcat学习资料1”所涵盖的知识点包括了Tomcat服务器的使用、配置以及Web项目的部署。Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,是一款开源的Java Servlet容器,广泛用于搭建Java Web...

    tomcat学习资料整理(不断更新)

    【标题】"Tomcat学习资料整理(不断更新)"揭示了这个压缩包文件是关于Tomcat服务器的深入学习资源,特别是关注其源码和使用的工具。Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,它是一个开源的、免费的...

    tomcat学习笔记

    【标题】:Tomcat学习笔记 【正文】: Tomcat是一款广泛应用的开源Web服务器和Java Servlet容器,由Apache软件基金会的Jakarta项目开发。它实现了Java Servlet和JavaServer Pages(JSP)规范,并且作为轻量级应用...

    Tomcat学习资料

    ### Tomcat学习资料知识点梳理 #### 一、Tomcat简介 **Tomcat** 是一个开源的轻量级Web应用服务器,适用于中小型系统和并发访问用户不是很多的场合。它由Apache Software Foundation(ASF)的Jakarta项目开发,因...

    Tomcat学习总结.zip

    《Tomcat学习总结》 Tomcat,作为Java Web应用程序的开源服务器,是Apache软件基金会Jakarta项目的一个核心组件。在本文中,我们将深入探讨Tomcat 8.5版本的学习要点,包括其工作原理、配置与优化,以及在实际开发...

    tomcat学习精华笔记

    【Tomcat 学习精华笔记】 Tomcat 是一个广泛应用的开源服务器,主要用于托管Java Web应用程序。它虽然不是严格意义上的应用服务器,但作为一个Servlet容器,它能够处理Servlet和JSP,并且具备了一些应用服务器的...

    tomcat 学习与分析总结资料

    《Tomcat学习与分析总结资料》是一份涵盖了Tomcat服务器核心知识的综合资源,适合对Java Web应用服务器感兴趣的开发者深入学习。Tomcat是Apache软件基金会的项目,是世界上最流行的开源Servlet容器,它实现了Java ...

    Tomcat学习

    【标题】:Tomcat学习 【内容】 Tomcat是一款开源的、基于Java Servlet和JavaServer Pages(JSP)技术的Web应用服务器,由Apache软件基金会的Jakarta项目维护。它是Java EE(现称为Jakarta EE)标准的重要组成部分...

    tomcat学习资料,内附tomcat安装过程及应用实例

    【标题】:Tomcat学习资料,内附Tomcat安装过程及应用实例 【内容】: Tomcat是一款由Apache软件基金会开发的开源Java Servlet容器,它实现了Java EE中的Web应用程序规范,是开发和部署小型到中型Java Web应用程序...

    tomcat学习与实践

    《Tomcat学习与实践》 在Java Web开发领域,Tomcat作为一款开源的Servlet容器,其重要性不言而喻。本系列文章将深入探讨Tomcat的内部机制、优化策略以及与Jetty的对比,旨在帮助读者理解并掌握Tomcat的使用与优化。...

    tomcat学习笔记.rar

    【标题】:Tomcat学习笔记 【描述】:Tomcat是一款广泛应用的开源Java Servlet容器,由Apache软件基金会下属的Tomcat项目开发维护。它主要用于部署和运行Java Web应用程序,包括Servlet和JSP。Tomcat以其轻量级、...

    Tomcat学习笔记

    《Tomcat学习笔记》 Tomcat是一款开源的Java Servlet容器,是Apache软件基金会下的Jakarta项目中的核心项目,主要用于运行Java Web应用程序。本笔记将详细阐述Tomcat的安装、配置、虚拟主机设置、JDBC数据库连接池...

    tomcat学习1:源码编译

    标题 "Tomcat学习1:源码编译" 涉及到的是对Apache Tomcat服务器的深入理解,尤其是从源代码层面进行构建和编译的过程。Apache Tomcat是一款开源的Java Servlet容器,它实现了Java EE的Web应用规范,是许多Java Web...

    Tomcat学习笔记,图片比较多,懒得写博客,先上传

    Tomcat学习笔记,图片比较多,懒得写博客,先上传

    tomcat学习资料收集整理

    tomcat学习资料收集整理。Tomcat可以运行Servlet和JSP,是一个小型的轻量级应用服务器,运行时占用系统资源小、扩展性好、支持负载平衡与邮件服务等开发应用系统中的常用功能,适用于中小型系统和并发访问用户不太多...

    tomcat官网版本Tomcat+Java学习资源

    【标题】:“Tomcat官网版本Tomcat+Java学习资源”是一个综合的学习资料包,主要针对的是Java开发中的关键工具——Apache Tomcat服务器以及相关的Java技术。Apache Tomcat是一款开源的Servlet容器,它实现了Java ...

    nginx和tomcat学习

    本篇文章将深入探讨这两个技术,并基于`Nginx`和`Tomcat`的学习进行详细讲解。 首先,让我们了解`Tomcat`。`Tomcat`是一个开源的Java Servlet容器,主要用于运行Java Web应用程序,特别是那些基于Java Servlet和...

Global site tag (gtag.js) - Google Analytics