Tomcat内部的生命周期组件LifeCycle接口实现与使用

作者: admin 分类: Tomcat 发布时间: 2019-11-19 17:27  阅读: 33 views

Catalina包含很多组件,当Catalina启动时,这些组件会一起启动,当关闭时,这些组件也会随之关闭。如,当servlet容器关闭时,它必须调用所有已经载入到容器中的servlet类的destory()方法,而session管理器必须将session对象保存到辅助存储其中。通过实现org.apache.catalina.Lifecycle接口,可以达到统一启动、关闭这些组件的效果

  1. Lifecycle接口

定义了生命周期的事件类型,和一些方法。组件必须提供start(),stop()方法的实现。

package org.apache.catalina;

public abstract 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 abstract void addLifecycleListener(LifecycleListener paramLifecycleListener);

  public abstract LifecycleListener[] findLifecycleListeners();

  public abstract void removeLifecycleListener(LifecycleListener paramLifecycleListener);

  //开启
  public abstract void start()
    throws LifecycleException;

  //关闭
  public abstract void stop()
    throws LifecycleException;
}

  1. LifecycleEvent类

生命周期事件类

package org.apache.catalina;

import java.util.EventObject;

public final class LifecycleEvent
  extends EventObject
{
  public LifecycleEvent(Lifecycle lifecycle, String type)
  {
    this(lifecycle, type, null);
  }

  public LifecycleEvent(Lifecycle lifecycle, String type, Object data)
  {
    super(lifecycle);
    this.lifecycle = lifecycle;
    this.type = type;
    this.data = data;
  }

  private Object data = null;
  private Lifecycle lifecycle = null;
  private String type = null;

  public Object getData()
  {
    return this.data;
  }

  public Lifecycle getLifecycle()
  {
    return this.lifecycle;
  }

  public String getType()
  {
    return this.type;
  }
}

3.LifecycleListener接口

监听事件接口

package org.apache.catalina;

public abstract interface LifecycleListener
{
  public abstract void lifecycleEvent(LifecycleEvent paramLifecycleEvent);
}

  1. LifecycleSupport类

实现了Lifecycle接口,并对某个时间注册了监听器组件必须提供的 addLifecycleListener(); findLifecycleListeners(); removeLifecycleListener();这三个方法进行实现。将所有注册的事件监听器存储到了一个集合对象中。可以管理监听器,并触发相应生命周期事件。

package org.apache.catalina.util;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;

public final class LifecycleSupport
{
  public LifecycleSupport(Lifecycle lifecycle)
  {
    this.lifecycle = lifecycle;
  }

  private Lifecycle lifecycle = null;
  private LifecycleListener[] listeners = new LifecycleListener[0];

  public void addLifecycleListener(LifecycleListener listener)
  {
    synchronized (this.listeners)
    {
      LifecycleListener[] results = new LifecycleListener[this.listeners.length + 1];
      for (int i = 0; i < this.listeners.length; i++) {
        results[i] = this.listeners[i];
      }
      results[this.listeners.length] = listener;
      this.listeners = results;
    }
  }

  public LifecycleListener[] findLifecycleListeners()
  {
    return this.listeners;
  }

  public void fireLifecycleEvent(String type, Object data)
  {
    LifecycleEvent event = new LifecycleEvent(this.lifecycle, type, data);
    LifecycleListener[] interested = null;
    synchronized (this.listeners)
    {
      interested = (LifecycleListener[])this.listeners.clone();
    }
    for (int i = 0; i < interested.length; i++) {
      interested[i].lifecycleEvent(event);
    }
  }

  public void removeLifecycleListener(LifecycleListener listener)
  {
    synchronized (this.listeners)
    {
      int n = -1;
      for (int i = 0; i < this.listeners.length; i++) {
        if (this.listeners[i] == listener)
        {
          n = i;
          break;
        }
      }
      if (n < 0) {
        return;
      }
      LifecycleListener[] results = new LifecycleListener[this.listeners.length - 1];

      int j = 0;
      for (int i = 0; i < this.listeners.length; i++) {
        if (i != n) {
          results[(j++)] = this.listeners[i];
        }
      }
      this.listeners = results;
    }
  }
}

5.SimpleContextLifecycleListener.java
实现LifecycleListener的servlet容器

package ex06.pyrmont.core;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;

public class SimpleContextLifecycleListener implements LifecycleListener {

  public void lifecycleEvent(LifecycleEvent event) {
    Lifecycle lifecycle = event.getLifecycle();
    System.out.println("SimpleContextLifecycleListener's event " +
      event.getType().toString());
    if (Lifecycle.START_EVENT.equals(event.getType())) {
      System.out.println("Starting context.");
    }
    else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
      System.out.println("Stopping context.");
    }
  }
}
  1. Servlet容器实现Lifecycle并对start,stop方法进行实现
package ex06.pyrmont.core;


import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.HashMap;
import javax.naming.directory.DirContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

...


import org.apache.catalina.util.LifecycleSupport;

public class SimpleContext implements Context, Pipeline, Lifecycle {

    ...  

  protected LifecycleSupport lifecycle = new LifecycleSupport(this);


  // implementation of the Lifecycle interface's methods
  public void addLifecycleListener(LifecycleListener listener) {
    lifecycle.addLifecycleListener(listener);
  }

  public LifecycleListener[] findLifecycleListeners() {
    return null;
  }

  public void removeLifecycleListener(LifecycleListener listener) {
    lifecycle.removeLifecycleListener(listener);
  }

  public synchronized void start() throws LifecycleException {
    if (started)
      throw new LifecycleException("SimpleContext has already started");

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
    started = true;
    try {
      // Start our subordinate components, if any
      if ((loader != null) && (loader instanceof Lifecycle))
        ((Lifecycle) loader).start();

      // 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();
      }

      // Start the Valves in our pipeline (including the basic),
      // if any
      if (pipeline instanceof Lifecycle)
        ((Lifecycle) pipeline).start();
      // Notify our interested LifecycleListeners
      lifecycle.fireLifecycleEvent(START_EVENT, null);
    }
    catch (Exception e) {
      e.printStackTrace();
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
  }

  public void stop() throws LifecycleException {
    if (!started)
      throw new LifecycleException("SimpleContext has not been started");
    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
    lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    started = false;
    try {
      // Stop the Valves in our pipeline (including the basic), if any
      if (pipeline instanceof Lifecycle) {
        ((Lifecycle) pipeline).stop();
      }

      // 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();
      }
      if ((loader != null) && (loader instanceof Lifecycle)) {
        ((Lifecycle) loader).stop();
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
  }

}

  1. 启动项目,创建监听的事件,这里是直接用了第五章的示例,可以自行简化一些代码以便理解。
package ex06.pyrmont.startup;

import ex06.pyrmont.core.SimpleContext;
import ex06.pyrmont.core.SimpleContextLifecycleListener;
import ex06.pyrmont.core.SimpleContextMapper;
import ex06.pyrmont.core.SimpleLoader;
import ex06.pyrmont.core.SimpleWrapper;
import org.apache.catalina.Connector;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Loader;
import org.apache.catalina.Mapper;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.http.HttpConnector;

public final class Bootstrap {
  public static void main(String[] args) {
    Connector connector = new HttpConnector();
    Wrapper wrapper1 = new SimpleWrapper();
    wrapper1.setName("Primitive");
    wrapper1.setServletClass("PrimitiveServlet");
    Wrapper wrapper2 = new SimpleWrapper();
    wrapper2.setName("Modern");
    wrapper2.setServletClass("ModernServlet");

    Context context = new SimpleContext();
    context.addChild(wrapper1);
    context.addChild(wrapper2);

    Mapper mapper = new SimpleContextMapper();
    mapper.setProtocol("http");
    LifecycleListener listener = new SimpleContextLifecycleListener();
    ((Lifecycle) context).addLifecycleListener(listener);
    context.addMapper(mapper);
    Loader loader = new SimpleLoader();
    context.setLoader(loader);
    // context.addServletMapping(pattern, name);
    context.addServletMapping("/Primitive", "Primitive");
    context.addServletMapping("/Modern", "Modern");
    connector.setContainer(context);
    try {
      connector.initialize();
      ((Lifecycle) connector).start();
      ((Lifecycle) context).start();

      // make the application wait until we press a key.
      System.in.read();
      ((Lifecycle) context).stop();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

这里找到一个比较简单的示例说明,可以参考:
https://blog.csdn.net/is_zhoufeng/article/details/49593655


   原创文章,转载请标明本文链接: Tomcat内部的生命周期组件LifeCycle接口实现与使用

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

更多阅读