Tomcat学习笔记

Posted 92#

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat学习笔记相关的知识,希望对你有一定的参考价值。

  生命周期事件

  Catalina包含有很多组件。当Catalina启动时,这些组件也会启动,同样,当Catalina关闭时,这些组件也随之关闭,通过实现org.apache.catalina.Lifecycle接口,可以达到统一启动/关闭这些组件的效果。

   实现Lifecycle接口的组件可以触发一个或多个下面的事件:BEFORE_START_EVENT、START_EVENT、AFTER_START_EVENT、BEFORE_STOP_EVENT、STOP_EVENT、AFTER_STOP_EVENT 。当组件启动时,正常会触发前3个事件,而关闭组件时,会触发后3个事件。如果Catalina组件可以触发事件,那么需要编写相应的事件监听器对这些事件进行响应。事件监听器是org.apache.catalina.LifecycleListener接口实例。

   tomcat内部架构各个核心组件的包含关系。例如server包含service,service包含container,一层层包含。而这种结构类似数据结构中的树形结构,对于tomcat的启动也是鉴于此,可以通过父容器启动子容器,这样可以达到只要启动根容器,从而启动所有的组件,同时便于管理达到统一启动、停止、关闭的效果。

                                                           

      生命周期采用是观察者模式(监听事件)。

                                                     

简单看一下tomcat的设计源码

事件对象LifecycleEvent

public final class LifecycleEvent extends EventObject {

    private static final long serialVersionUID = 1L;


    // ----------------------------------------------------------- Constructors

    /**
     * Construct a new LifecycleEvent with the specified parameters.
     *
     * @param lifecycle Component on which this event occurred
     * @param type Event type (required)
     * @param data Event data (if any)
     */
    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {

        super(lifecycle);
        this.type = type;
        this.data = data;
    }


    // ----------------------------------------------------- Instance Variables


    /**
     * The event data associated with this event.
     */
    private Object data = null;


    /**
     * The event type this instance represents.
     */
    private String type = null;


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


    /**
     * Return the event data of this event.
     */
    public Object getData() {

        return (this.data);

    }


    /**
     * Return the Lifecycle on which this event occurred.
     */
    public Lifecycle getLifecycle() {

        return (Lifecycle) getSource();

    }

    /**
     * Return the event type of this event.
     */
    public String getType() {

        return (this.type);

    }

}

事件监听接口LifecycleListener

public interface LifecycleListener {


    /**
     * Acknowledge the occurrence of the specified event.
     *
     * @param event LifecycleEvent that has occurred
     */
    public void lifecycleEvent(LifecycleEvent event);


}

事件监听实现类JasperListener

public void lifecycleEvent(LifecycleEvent event) {

        if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) {
            try {
                // Set JSP factory
                Class.forName("org.apache.jasper.compiler.JspRuntimeContext",
                              true,
                              this.getClass().getClassLoader());
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                // Should not occur, obviously
                log.warn("Couldn\'t initialize Jasper", t);
            }
            // Another possibility is to do directly:
            // JspFactory.setDefaultFactory(new JspFactoryImpl());
        }

    }

事件监听类LifecycleSupport

public void addLifecycleListener(LifecycleListener listener) {

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

    }
//触发事件
public void fireLifecycleEvent(String type, Object data) {

        LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
        LifecycleListener interested[] = listeners;
        for (int i = 0; i < interested.length; i++)
            interested[i].lifecycleEvent(event);

    }
//移除事件
public void removeLifecycleListener(LifecycleListener listener) {

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

    }

       事件源 ServerStandard@startInternal()

//触发事件
protected void startInternal() throws LifecycleException {

        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);

        globalNamingResources.start();
        
        // Start our defined Services
        synchronized (services) {
            for (int i = 0; i < services.length; i++) {
                services[i].start();
            }
        }
    }

下面写了一个简单观察者模式的例子,便于理解。

import java.util.ArrayList;
import java.util.List;

class MacBookPro{
    
    public List<ITClient> clients = new ArrayList<ITClient>();

    public void addClientListener(ITClient client){
        clients.add(client);
    }
    public void notifyClient(String info){
        //通知所有放入监听者
        clients.forEach(x->x.receiveInfo(info));
    }
}
class ITClient{
    
    private String name;
    
    public ITClient(String name)
    {
        this.name = name;
    }
    public void receiveInfo(String info){
        System.out.println(this.name+" :: "+info);
    }
}
public class StateTest
{
    public static void main(String[] args)
    {
        MacBookPro mbp = new MacBookPro();
        ITClient c1 = new ITClient("员工1");
        ITClient c2 = new ITClient("员工2");
        ITClient c3 = new ITClient("员工3");
        mbp.addClientListener(c1);
        mbp.addClientListener(c2);
        mbp.addClientListener(c3);
        System.out.println("促销活动开始了");
        mbp.notifyClient("京东618大减价");
    }
}

结果:

促销活动开始了
员工1 :: 京东618大减价
员工2 :: 京东618大减价
员工3 :: 京东618大减价

 

以上是关于Tomcat学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

在Tomcat的安装目录下conf目录下的server.xml文件中增加一个xml代码片段,该代码片段中每个属性的含义与用途

tomcat学习笔记手写tomcat

tomcat学习笔记手写tomcat

tomcat学习笔记Tomcat源码剖析

tomcat学习笔记Tomcat源码剖析

DOM探索之基础详解——学习笔记