通过Server可以让我们以一种优雅的方式来启动/关闭整个系统。
从Catalina类看出,启动整个服务只需要通过server.start()就可以,它会带动其中所有组件的启动,然后无期限的等待关闭命令, 关闭系统,则是通过向指定端口发送一条命令, 调用server.stop()就可关闭所有的组件.
Tomcat使用的就是这个标准Server类,它实现了Server接口类
public final class StandardServer
implements Lifecycle, Server {
public StandardServer() {
super();
ServerFactory.setServer(this);
globalNamingResources = new NamingResources(); //????????这些有什么用
globalNamingResources.setContainer(this);
if (isUseNaming()) {
if (namingContextListener == null) { //????????这些有什么用
namingContextListener = new NamingContextListener();
namingContextListener.setDebug(getDebug());
addLifecycleListener(namingContextListener);
}
}
}
}
StandardServer的构造函数中好像是初始化Global naming resources.(究竟有什么用,和启动参数-nonaming有什么关系,naming有什么用),后续研究
现阶段关心的是Server类中的初始化、等待、开始、停止方法。
public void initialize()
throws LifecycleException {
if (initialized)
throw new LifecycleException (
sm.getString("standardServer.initialize.initialized"));
initialized = true;
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].initialize();
}
}
使用一个名为initialized的变量来防止服务器组件初始化两次。依次调用server包含的service的初始化过程。值得注意的是,stop()函数并没有重置initialized为false,所以如果服务器组件关闭后再启动,是不会进行初始化的
public void start() throws LifecycleException {
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("standardServer.start.started"));
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); //结尾处有细讲Listener
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our defined Services
synchronized (services) {
for (int i = 0; i < services.length; i++) {
if (services[i] instanceof Lifecycle)
((Lifecycle) services[i]).start();
}
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
防止重复启动。依次调用server包含的service的start()函数。stop()函数会重置started为false
public void await() {
// Set up a server socket to wait on
ServerSocket serverSocket = null;
try {
serverSocket =
new ServerSocket(port, 1,
InetAddress.getByName("127.0.0.1"));
} catch (IOException e) {
System.err.println("StandardServer.await: create[" + port
+ "]: " + e);
e.printStackTrace();
System.exit(1);
}
// Loop waiting for a connection and a valid command
while (true) {
// Wait for the next connection
Socket socket = null;
InputStream stream = null;
try {
socket = serverSocket.accept();
socket.setSoTimeout(10 * 1000); // Ten seconds
stream = socket.getInputStream();
} catch (AccessControlException ace) {
System.err.println("StandardServer.accept security exception: "
+ ace.getMessage());
continue;
} catch (IOException e) {
System.err.println("StandardServer.await: accept: " + e);
e.printStackTrace();
System.exit(1);
}
// Read a set of characters from the socket
StringBuffer command = new StringBuffer();
int expected = 1024; // Cut off to avoid DoS attack
while (expected < shutdown.length()) {
if (random == null)
random = new Random(System.currentTimeMillis());
expected += (random.nextInt() % 1024);
}
while (expected > 0) {
int ch = -1;
try {
ch = stream.read();
} catch (IOException e) {
System.err.println("StandardServer.await: read: " + e);
e.printStackTrace();
ch = -1;
}
if (ch < 32) // Control character or EOF terminates loop
break;
command.append((char) ch);
expected--;
}
// Close the socket now that we are done with it
try {
socket.close();
} catch (IOException e) {
;
}
// Match against our command string
boolean match = command.toString().equals(shutdown);
if (match) {
break;
} else
System.err.println("StandardServer.await: Invalid command '" + command.toString() + "' received");
}
// Close the server socket and return
try {
serverSocket.close();
} catch (IOException e) {
;
}
}
wait()函数的作用在Catalina类中已经有讲过,就是新开一个侦听端口,无限循环直至端口接收到关闭命令,则退出循环,关闭端口.
public void stop() throws LifecycleException {
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("standardServer.stop.notStarted"));
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
// Stop our defined Services
for (int i = 0; i < services.length; i++) {
if (services[i] instanceof Lifecycle)
((Lifecycle) services[i]).stop();
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
}
与start()类似.
服务组件(service)可以有一个container和多个connector(目前你只用知道connector是接受http请求的,container是处理http请求的), 但所有的connector都会与这一个container关联.
来看看提供的StandardService类
public final class StandardService
implements Lifecycle, Service {
/**
* The set of Connectors associated with this Service.
*/
private Connector connectors[] = new Connector[0];
/**
* The Container associated with this Service.
*/
private Container container = null;
/**
* The <code>Server</code> that owns this Service, if any.
* 这个service属于哪个server
*/
private Server server = null;
}
StandardService中包含设置container,添加删除container的代码,需要注意的是container包含connector中,所以在设置container或者设置connector时,都需要更新对应的另外一个对象的内容。
public void setContainer(Container container) {
//解除老container与service的关系,---------并调用oldContainer.stop()---------
Container oldContainer = this.container;
if ((oldContainer != null) && (oldContainer instanceof Engine))
((Engine) oldContainer).setService(null);
this.container = container;
if ((this.container != null) && (this.container instanceof Engine))
((Engine) this.container).setService(this);
if (started && (this.container != null) &&
(this.container instanceof Lifecycle)) {
try {
((Lifecycle) this.container).start();
} catch (LifecycleException e) {
;
}
}
//注意下边这中同步写法................
//改变每个connector的container
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++)
connectors[i].setContainer(this.container);
}
//看这里,老Container.stop()
if (started && (oldContainer != null) &&
(oldContainer instanceof Lifecycle)) {
try {
((Lifecycle) oldContainer).stop();
} catch (LifecycleException e) {
;
}
}
// Report this property change to interested listeners
support.firePropertyChange("container", oldContainer, this.container);
}
就像上面展示的,注意两点:1. 解除老container与service的关系,并调用oldContainer.stop();2. 修改每个container的container(包含在同步代码块中)。
类似的,添加时,注意设置connector的归属service以及container,移除connector时也要注意调用其stop()方法并解除其service和container。具体可查看源码
public void initialize()
throws LifecycleException {
if (initialized)
throw new LifecycleException (
sm.getString("standardService.initialize.initialized"));
initialized = true;
// Initialize our defined Connectors
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
connectors[i].initialize();
}
}
}
initialized变量防止重复初始化,并调用每个connector的initialize()方法。container无需初始化,后续后继续分析connector和container。
public void start() throws LifecycleException {
// Validate and update our current component state
if (started) {
throw new LifecycleException
(sm.getString("standardService.start.started"));
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
System.out.println
(sm.getString("standardService.start.name", this.name));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our defined Container first
if (container != null) {
synchronized (container) {
if (container instanceof Lifecycle) {
((Lifecycle) container).start();
}
}
}
// Start our defined Connectors second
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
if (connectors[i] instanceof Lifecycle)
((Lifecycle) connectors[i]).start();
}
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
调用每个connector和container的start()方法。
stop()方法类似,就不展示了。
上面代码中看到的lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null); lifecycle.fireLifecycleEvent(STOP_EVENT, null);
在Tomcat源码中非常常见,是Tomcat用来控制组件生命周期的一种手段。
用通俗的比喻来说,就是当前的server带着一群小弟(Listener, 也叫observer), 当大哥server要进行stop操作时,操作之前,先吼一嗓子(lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
), 所有的小弟都会听到,并且做一些准备工作,然后又吼一嗓子开始干活了(lifecycle.fireLifecycleEvent(STOP_EVENT, null);
), 所有小弟开始干正事了,然后大哥server也开始干正事了,完事后,大哥server也要和小弟通报一声(lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
), 小弟们都知道了,开始各自收拾东西。
上面是一个形象的例子,具体看观察者模式的实现,可查看这个观察者模式