Chapter 6: Lifecycle
Overview
Catalina consists of many components. When Catalina is started, these components need to be started as well. When Catalina is stopped, these components must also be given a chance to do a clean-up. For example, when the container is stopped, it must invoke the destroy method of all loaded servlets and the session manager must save the session objects to secondary storage. A consistent mechanism for starting and stopping components is achieved by implementing the org.apache.catalina.Lifecycle interface.
Catalina
由许多组件组成。当启动Catalina时,这些组件也需要被启动。
当停止 Catalina
时,这些组件也必须有机会进行清理工作。
例如,当容器停止时,它必须调用所有加载的 servlet
的 destroy
方法,而会话管理器必须将会话对象保存到辅助存储中。
通过实现org.apache.catalina.Lifecycle
接口,可以实现一种一致的启动和停止组件的机制。
A component implementing the Lifecycle interface can also trigger one or many of the following events: BEFORE_START_EVENT, START_EVENT, AFTER_START_EVENT, BEFORE_STOP_EVENT, STOP_EVENT, and AFTER_STOP_EVENT. The first three events are normally fired when the component is started and the last three when the component is stopped. An event is represented by the org.apache.catalina.LifecycleEvent class. And, of course, if a Catalina component can trigger events, there must be event listeners that you can write to respond to those events. A listener is represented by the org.apache.catalina.LifecycleListener interface.
实现Lifecycle接口的组件还可以触发以下一种或多种事件:
BEFORE_START_EVENT
START_EVENT
AFTER_START_EVENT
BEFORE_STOP_EVENT
STOP_EVENT
AFTER_STOP_EVENT
前三个事件通常在组件启动时触发,后三个事件在组件停止时触发。
事件由org.apache.catalina.LifecycleEvent
类表示。
当然,如果Catalina
组件可以触发事件,那么肯定还有事件监听器,您可以编写这些监听器来响应这些事件。
监听器由org.apache.catalina.LifecycleListener
接口表示。
This chapter will discuss these three types Lifecycle, LifecycleEvent, and LifecycleListener. In addition, it will also explain a utility class called LifecycleSupport that provides an easy way for a component to fire lifecycle events and deal with lifecycle listeners. In this chapter, you will build a project with classes that implement the Lifecycle interface. The application is based on the application in Chapter 5.
本章将讨论这三种类型的Lifecycle
、LifecycleEvent
和LifecycleListener
。
此外,还将解释一个名为 LifecycleSupport
的实用类,它提供了一种简单的方式让组件触发生命周期事件并处理生命周期监听器。
在本章中,您将构建一个实现 Lifecycle
接口的类的项目。
该应用程序基于第5章的应用程序。
The Lifecycle Interface
The design of Catalina allows a component to contain other components. For example, a container can contain components such as a loader, a manager, etc. A parent component is responsible for starting and stopping its child components. The design of Catalina is such that all components but one are put "in custody" of a parent component so that a bootstrap class needs only start one single component. This single start/stop mechanism is made possible through the Lifecycle interface. Take a look at the Lifecycle interface in Listing 6.1.
Catalina
的设计允许一个组件包含其他组件。
例如,一个容器可以包含加载器、管理器等组件。
父组件负责启动和停止其子组件。
Catalina
的设计是这样的,除了一个组件外,其他所有组件都被"托管"给了一个父组件,因此引导类只需要启动一个单一组件。
通过Lifecycle接口,实现了这种单一的启动/停止机制。请查看代码清单6.1中的Lifecycle
接口。
Listing 6.1: The Lifecycle interface
代码清单6.1:Lifecycle
接口
package org.apache.catalina;
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;
The most important methods in Lifecycle are start and stop. A component provides implementations of these methods so that its parent component can start and stop it. The other three methods—addLifecycleListener, findLifecycleListeners, and removeLifecycleListener—are related to listeners. A component can have listeners that are interested in an event that occurs in that component. When an event occurs, the listener interested in that event will be notified. The names of the six events that can be triggered by a Lifecycle instance are defined in public static final Strings of the interface
Lifecycle
中最重要的方法是 start
和 stop
。
组件提供这些方法的实现,以便其父组件可以启动和停止它。
另外三个方法—— addLifecycleListener
、findLifecycleListeners
和 removeLifecycleListener
——与监听器相关。
组件可以拥有对在该组件中发生的事件感兴趣的监听器。
当事件发生时,将通知对该事件感兴趣的监听器。
可以由 Lifecycle
实例触发的六个事件的名称在接口的 public static final Strings
中定义。
The LifecycleEvent Class
The org.apache.catalina.LifecycleEvent class represents a lifecycle event and is presented in Listing 6.2.
org.apache.catalina.LifecycleEvent
类表示生命周期事件,如清单 6.2 所示。
Listing 6.2: The org.apache.catalinaLifecycleEvent interface
清单 6.2:org.apache.catalinaLifecycleEvent
接口
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);
}
}
The LifecycleListener Interface
The org.apache.catalina.LifecycleListener interface represents a lifecycle listener and is given in Listing 6.3.
org.apache.catalina.LifecycleListener
接口表示生命周期监听器,在清单 6.3 中给出。
Listing 6.3: The org.apache.catalina.LifecycleListener interface
清单 6.3:org.apache.catalina.LifecycleListener
接口
package org.apache.catalina;
import java.util.EventObject;
public interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}
There is only one method in this interface, lifecycleEvent. This method is invoked when an event the listener is interested in fires.
该接口中只有一个方法,即 lifecycleEvent
。
当监听器感兴趣的事件触发时,就会调用该方法。
The LifecycleSupport Class
A component implementing Lifecycle and allowing a listener to register its interest in its events must provide code for the three listener-related methods in the Lifecycle interface (addLifecycleListener, findLifecycleListeners, and removeLifecycleListener). That component then has to store all listeners added to it in an array or ArrayList or a similar object. Catalina provides a utility class for making it easy for a component to deal with listeners and fire lifecycle events:
实现 Lifecycle
接口并允许监听器注册其对事件的兴趣的组件必须为 Lifecycle
接口中的三个与监听器相关的方法(addLifecycleListener
、findLifecycleListeners
和 removeLifecycleListener
)提供代码。
然后,该组件必须将所有添加到其中的监听器存储在数组、ArrayList或类似的对象中。
Catalina
提供了一个实用类,使组件可以轻松处理监听器和触发生命周期事件:
org.apache.catalina.util.LifecycleSupport. The LifecycleSupport class is given in Listing 6.4.
org.apache.catalina.util.LifecycleSupport
。LifecycleSupport
类在列表6.4中给出。
Listing 6.4: The LifecycleSupport class
列表6.4:LifecycleSupport
类
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) {
super();
this.lifecycle = lifecycle;
}
private Lifecycle lifecycle = null;
private LifecycleListener listeners[] = new LifecycleListener[0];
public void addLifecycleListener(LifecycleListener listener) {
synchronized (listeners) {
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 LifecycleListener[] findLifecycleListeners() {
return listeners;
}
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);
}
public void removeLifecycleListener(LifecycleListener listener) {
synchronized (listeners) {
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;
}
}
}
As you can see in Listing 6.4, the LifecycleSupport class stores all lifecycle listeners in an array called listeners that initially has no member.
如清单 6.4 所示,LifecycleSupport
类将所有生命周期侦听器存储在一个名为 listeners
的数组中,该数组最初没有成员。
private LifecycleListener listeners[] = new LifecycleListener[0];
When a listener is added in the addLifecycleListener method, a new array is created with the size of the number of elements in the old array plus one. Then, all elements from the old array are copied to the new array and the new listener is added. When a listener is removed in the removeLifecycleListener method, a new array is also created with the size of the number of elements in the old array minus one. Then, all elements except the one removed are copied to the new array.
在 addLifecycleListener
方法中添加监听器时,会创建一个新的数组,其大小为旧数组中元素数量加一。
然后,将所有旧数组中的元素复制到新数组中,并添加新的监听器。
在 removeLifecycleListener
方法中移除监听器时,也会创建一个新的数组,其大小为旧数组中元素数量减一。
然后,将除被移除的元素外的所有元素复制到新数组中。
The fireLifecycleEvent method fires a lifecycle event. First, it clones the listeners array. Then, it calls the lifecycleEvent method of each member, passing the triggered event.
fireLifecycleEvent
方法触发生命周期事件。
首先,它克隆监听器数组。然后,调用每个成员的 lifecycleEvent
方法,传递触发的事件。
A component implementing Lifecycle can use the LifecycleSupport class. For example, the SimpleContext class in the application accompanying this chapter declares the following variable:
实现 Lifecycle
接口的组件可以使用 LifecycleSupport
类。例如,本章附带的应用程序中的SimpleContext类声明了以下变量:
protected LifecycleSupport lifecycle = new LifecycleSupport(this);
To add a lifecycle listener, the SimpleContext class calls the addLifecycleListener method of the LifecycleSupport class:
要添加生命周期监听器,SimpleContext
类会调用 LifecycleSupport
类的 addLifecycleListener
方法:
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
To remove a lifecycle listener, the SimpleContext class calls the removeLifecycleListener method of the LifecycleSupport class.
要移除生命周期监听器,SimpleContext
类会调用 LifecycleSupport
类的 removeLifecycleListener
方法。
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
To fire an event, the SimpleContext class calls the fireLifecycleEvent method of the LifecycleSupport class, such as in the following line of code:
要触发事件,SimpleContext
类会调用 LifecycleSupport
类的 fireLifecycleEvent
方法,例如下面这行代码:
lifecycle.fireLifecycleEvent(START_EVENT, null);
The Application
The application accompanying this chapter builds upon the application in Chapter 5 and illustrates the use of the Lifecycle interface and lifecycle-related types. It contains one context and two wrappers as well as a loader and a mapper. The components in this application implement the Lifecycle interface and a listener is used for the context. The two valves in Chapter 5 are not used here to make the application simpler. The class diagram of the application is shown in Figure 6.1. Note that a number of interfaces (Container, Wrapper, Context, Loader, Mapper) and classes (SimpleContextValve, SimpleContextMapper, and SimpleWrapperValve) are not included in the diagram.
本章附带的应用程序建立在第5章的应用程序基础上,演示了 Lifecycle
接口和与其相关的类型的使用。
它包含一个上下文和两个包装器,以及一个加载器和一个映射器。
该应用程序中的组件实现了Lifecycle
接口,并使用监听器来处理上下文。
本应用程序中并未使用第5章中的两个阀门,以使应用程序更简单。应用程序的类图如图6.1所示。
请注意,图中未包含一些接口(Container
、Wrapper
、Context
、Loader
、Mapper
)和类(SimpleContextValve
、SimpleContextMapper
和 SimpleWrapperValve
)。
Figure 6.1: The class diagram of the accompanying application
图6.1:伴随应用程序的类图
Note that the SimpleContextLifecycleListener class represents a listener class for the SimpleContext class. The SimpleContextValve, SimpleContextMapper, and SimpleWrapperValve classes are the same as the ones in Chapter 5 and will not be discussed again here.
请注意,SimpleContextLifecycleListener
类代表 SimpleContext
类的监听器类。
SimpleContextValve
、SimpleContextMapper
和 SimpleWrapperValve
类与第5章中的类相同,在此不再讨论。
ex06.pyrmont.core.SimpleContext
The SimpleContext class in this application is similar to the one in Chapter 5, except that it now implements the Lifecycle interface. The SimpleContext class uses the following variable to reference a LifecycleSupport instance.
这个应用程序中的 SimpleContext
类与第5章中的类相似,只是现在它实现了 Lifecycle
接口。 SimpleContext
类使用以下变量引用一个 LifecycleSupport
实例。
protected LifecycleSupport lifecycle = new LifecycleSupport(this);
It also uses a boolean named started to indicate if the SimpleContext instance has been started. The SimpleContext class provides implementation of the methods from the Lifecycle interface. Listing 6.5 presents these methods.
它还使用了一个名为 started
的布尔变量来表示 SimpleContext
实例是否已启动。
SimpleContext
类提供了 Lifecycle
接口方法的实现。
第6.5节列出了这些方法。
Listing 6.5: Methods from the Lifecycle interface.
第6.5节:Lifecycle
接口的方法。
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);
}
Notice how the start method starts all child containers and associated components such as the Loader, Pipeline, and Mapper, and how the stop method stops them? Using this mechanism, to start all the components in the container module, you just need to start the highest component in the hierarchy (in this case the SimpleContext instance). To stop them, you only have to stop the same single component.
注意到 start
方法是如何启动所有子容器和相关组件(如加载器、管道和映射器)的,以及 stop
方法是如何停止它们的吗?
使用这种机制,要启动容器模块中的所有组件,只需启动层次结构中最高的组件(在本例中为 SimpleContext
实例)即可。要停止这些组件,只需停止同一个组件即可。
The start method in SimpleContext begins by checking, if the component has been started previously. If it has, it throws a LifecycleException
SimpleContext
中的启动方法首先会检查组件是否已被启动。
如果是,则抛出生命周期异常(LifecycleException
)。
if (started)
throw new LifecycleException(
"SimpleContext has already started");
It then raises the BEFORE_START_EVENT event.
然后,它会引发 BEFORE_START_EVENT
事件。
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
As a result, every listener that has registered its interest in the SimpleContext instance's events will be notified. In this application, one listener of type SimpleContextLifecycleListener registers its interest. We will see what happens with this listener when we discuss the SimpleContextLifecycleListener class.
因此,每个已注册其对 SimpleContext
实例事件感兴趣的监听器都会收到通知。
在此应用程序中,有一个 SimpleContextLifecycleListener
类型的监听器注册了其兴趣。我们将在讨论 SimpleContextLifecycleListener
类时了解该监听器的情况。
Next, the start method sets the started boolean to true to indicate that the component has been started.
接下来,start
方法会将 started
布尔值设为 true
,表示组件已启动。
started = true;
The start method then starts all the components and its child container. Currently there are two components that implement the Lifecycle interface, SimpleLoader and SimplePipeline. The SimpleContext has two wrappers as its children. These wrappers are of type SimpleWrapper that also implements the Lifecycle interface.
然后,start 方法会启动所有组件及其子容器。目前有两个组件实现了生命周期接口,即 SimpleLoader
和 SimplePipeline
。
SimpleContext
有两个包装器作为其子容器。这些包装器属于 SimpleWrapper
类型,也实现了生命周期接口。
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();
After the components and children are started, the start method raises two events: START_EVENT and AFTER_START_EVENT.
组件和子节点启动后,启动方法会引发两个事件: START_EVENT
和 AFTER_START_EVENT
。
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
.
.
.
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
The stop method first checks if the instance has been started. If not, it throws a LifecycleException
stop
方法首先检查实例是否已启动。如果没有,则抛出一个 LifecycleException
if (!started)
throw new LifecycleException(
"SimpleContext has not been started");
It then generates the BEFORE_STOP_EVENT and STOP_EVENT events, and reset the started boolean.
然后,它会生成 BEFORE_STOP_EVENT
和 STOP_EVENT
事件,并重置已启动布尔值。
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
Next, the stop method stops all components associated with it and the SimpleContext instance's child containers.
接下来,stop
方法会停止与其相关的所有组件以及 SimpleContext
实例的子容器。
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();
}
}
Finally, it raises the AFTER_STOP_EVENT event.
最后,它会引发 AFTER_STOP_EVENT
事件。
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
ex06.pyrmont.core.SimpleContextLifecycleListener
The SimpleContextLifecycleListener class represents a listener for a SimpleContext instance. It is given in Listing 6.6.
SimpleContextLifecycleListener
类表示 SimpleContext
实例的监听器。该类如清单 6.6 所示。
Listing 6.6: The SimpleContextLifecycleListener class
清单 6.6:SimpleContextLifecycleListener
类
package ex06.pyrmont.core;
import org.apache.catalina.Context;
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.");
}
}
}
The implementation of the lifecycleEvent method in the SimpleContextLifecycleListener class is simple. It simply prints the type of the event raised. If it is a START_EVENT, the lifecycleEvent method prints Starting context. If the event is a STOP_EVENT, then it prints Stopping context.
SimpleContextLifecycleListener
类中的 lifecycleEvent
方法的实现非常简单。
它只需打印引发事件的类型。如果是 START_EVENT
,lifecycleEvent
方法就会打印 "开始 "上下文。
如果事件是 STOP_EVENT
,则打印 Stopping
上下文。
ex06.pyrmont.core.SimpleLoader
The SimpleLoader class is similar to the one in Chapter 5, except that in this application the class implements the Lifecycle interface. The method implementation for the Lifecycle interface for this class does not do anything other than printing a string to the console. More importantly, however, by implementing the Lifecycle interface, a SimpleLoader instance can be started by its associated container.
SimpleLoader
类与第5章中的类相似,不同之处在于该应用程序中的类实现了 Lifecycle
接口。
对于该类的 Lifecycle
接口的方法实现除了向控制台打印一个字符串之外,不做任何其他操作。
然而,更重要的是,通过实现 Lifecycle
接口,一个 SimpleLoader
实例可以被其关联的容器启动。
The methods from the Lifecycle interface in SimpleLoader are given in Listing 6.7.
SimpleLoader
中的 Lifecycle
接口方法在6.7节中给出。
public void addLifecycleListener(LifecycleListener listener) { }
public LifecycleListener[] findLifecycleListeners() {
return null;
}
public void removeLifecycleListener(LifecycleListener listener) { }
public synchronized void start() throws LifecycleException {
System.out.println("Starting SimpleLoader");
}
public void stop() throws LifecycleException { }
ex06.pyrmont.core.SimplePipeline
In addition to the Pipeline interface, the SimplePipeline class implements the Lifecycle interface. The methods from the Lifecycle interface are left blank but now an instance of this class can be started from its associated container. The rest of the class is similar to the SimplePipeline class in Chapter 5.
除了 Pipeline
接口之外,SimplePipeline
类还实现了 Lifecycle
接口。
Lifecycle
接口的方法留空,但现在可以从其关联的容器启动该类的实例。该类的其余部分与第5章中的 SimplePipeline
类相似。
ex06.pyrmont.core.SimpleWrapper
This class is similar to the ex05.pyrmont.core.SimpleWrapper class. In this application, it implements the Lifecycle interface so that it can be started from its parent container. In this application most of the methods from the Lifecycle interface are left blank except the start and stop methods. Listing 6.8 presents the method implementation from the Lifecycle interface.
这个类与ex05.pyrmont.core.SimpleWrapper
类相似。在本应用程序中,它实现了Lifecycle接口,以便可以从其父容器启动。
在本应用程序中,Lifecycle
接口的大多数方法留空,只有 start
和 stop
方法不为空。
图6.8展示了Lifecycle
接口的方法实现。
Listing 6.8: The methods from the Lifecycle interface
图6.8:Lifecycle接口的方法
public void addLifecycleListener(LifecycleListener listener) {
}
public LifecycleListener[] findLifecycleListeners() {
return null;
}
public void removeLifecycleListener(LifecycleListener listener) (}
public synchronized void start()throws LifecycleException{
System.out.println("Starting Wrapper "+name);
if(started)
throw new LifecycleException("Wrapper already started");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT,null);
started=true;
// Start our subordinate components, if any
if((loader!=null)&&(loader instanceof Lifecycle))
((Lifecycle)loader).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);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT,null);
}
public void stop()throws LifecycleException{
System.out.println("Stopping wrapper "+name);
// Shut down our servlet instance (if it has been initialized)
try{
instance.destroy();
}
catch(Throwable t){
}
instance=null;
if(!started)
throw new LifecycleException("Wrapper "+name+" not started");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT,null);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(STOP_EVENT,null);
started=false;
// Stop the Valves in our pipeline (including the basic), if any
if(pipeline instanceof Lifecycle){
((Lifecycle)pipeline).stop();
}
// Stop our subordinate components, if any
if((loader!=null)&&(loader instanceof Lifecycle)){
((Lifecycle)loader).stop();
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT,null);
}
The start method in SimpleWrapper is similar to the start method in the SimpleContext class. It starts any components added to it (currently, there is none) and triggers the BEFORE_START_EVENT, START_EVENT, and AFTER_START_EVENT events.
SimpleWrapper
中的 start
方法与 SimpleContext
类中的 start 方法类似。
它会启动添加到其中的任何组件(目前没有组件),并触发 BEFORE_START_EVENT
、START_EVENT
和 AFTER_START_EVENT
事件。
The stop method in SimpleWrapper is even more interesting. After printing a simple string, it invokes the destroy method of the servlet instance.
SimpleWrapper
中的 stop
方法更加有趣。
在打印一个简单的字符串后,它会调用 servlet
实例的 destroy
方法。
System.out.println("Stopping wrapper " + name);
// Shut down our servlet instance (if it has been initialized)
try {
instance.destroy();
}
catch (Throwable t) {
}
instance = null;
Then, it checks if the wrapper has been started. If not, it throws a LifecycleException.
然后,它会检查包装器是否已启动。
如果没有,则抛出 LifecycleException
。
if (!started)
throw new LifecycleException("Wrapper " + name + " not started");
Next, it triggers the BEFORE_STOP_EVENT and STOP_EVENT events and reset the started boolean.
接下来,它会触发 BEFORE_STOP_EVENT
和 STOP_EVENT
事件,并重置已启动布尔值。
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
Next, it stops the loader and pipeline components associated with it. In this application, the SimpleWrapper instances do not have a loader.
接下来,它会停止与之相关的加载器和管道组件。
在此应用程序中,SimpleWrapper
实例没有加载器。
// Stop the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).stop();
}
// Stop our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}
Finally, it triggers the AFTER_STOP_EVENT event.
最后,它会触发 AFTER_STOP_EVENT
事件。
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
Running the Application
To run the application in Windows, from the working directory, type the following:
要在 Windows
中运行应用程序,请在工作目录中键入以下内容:
java -classpath ./lib/servlet.jar;./ ex06.pyrmont.startup.Bootstrap
In Linux, you use a colon to separate two libraries.
在 Linux
中,使用冒号分隔两个库。
java -classpath ./lib/servlet.jar:./ ex06.pyrmont.startup.Bootstrap
You will see the following message on the console. Notice how the various events are fired?
您将在控制台看到以下信息。
注意到各种事件是如何触发的吗?
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
SimpleContextLifecycleListener's event before_start
Starting SimpleLoader
Starting Wrapper Modern
Starting Wrapper Primitive
SimpleContextLifecycleListener's event start
Starting context.
SimpleContextLifecycleListener's event after_start
To invoke PrimitiveServlet, you use the following URL in your browser.
要调用 PrimitiveServlet
,请在浏览器中使用以下 URL。
http://localhost:8080/Primitive
To invoke ModernServlet, you use the following URL.
要调用 ModernServlet
,请使用以下 URL。
Summary
In this chapter you have learned how to work with the Lifecycle interface. This interface defines the lifecycle for a component and provides an elegant way to send events to other components. In addition, the Lifecycle interface also makes it possible to start and stop all the components in Catalina by one single start/stop.
在本章中,你将学习如何使用生命周期接口。
该接口定义了组件的生命周期,并提供了一种向其他组件发送事件的优雅方式。
此外,生命周期接口还可以通过一次启动/停止来启动和停止 Catalina
中的所有组件。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。