Tomcat内部的生命周期组件LifeCycle接口实现与使用
Catalina包含很多组件,当Catalina启动时,这些组件会一起启动,当关闭时,这些组件也会随之关闭。如,当servlet容器关闭时,它必须调用所有已经载入到容器中的servlet类的destory()方法,而session管理器必须将session对象保存到辅助存储其中。通过实现org.apache.catalina.Lifecycle接口,可以达到统一启动、关闭这些组件的效果
- 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;
}
- 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);
}
- 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.");
}
}
}
- 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);
}
}
- 启动项目,创建监听的事件,这里是直接用了第五章的示例,可以自行简化一些代码以便理解。
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接口实现与使用