the application
这个应用程序展示了如何使用一个server和一个service。尤其是,演示了如何在StandardServer类中使用start和stop机制。这个应用中有三个类。第一个是SimpleContextConfig类,与第十三章中的应用程序的类完全相同。其他的两个类是Bootstrap和Stopper。Bootstrap类用于启动这个应用程序,Stopper类用于关闭它。
the Bootstrap Class
package ex14.pyrmont.startup;
import ex14.pyrmont.core.SimpleContextConfig;
import org.apache.catalina.Connector;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Loader;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.Wrapper;
import org.apache.catalina.connector.http.HttpConnector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.core.StandardService;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.loader.WebappLoader;
public final class Bootstrap {
public static void main(String[] args) {
System.setProperty("catalina.base",
System.getProperty("user.dir"));
Connector connector = new HttpConnector();
Wrapper wrapper1 = new StandardWrapper();
wrapper1.setName("Primitive");
wrapper1.setServletClass("PrimitiveServlet");
Wrapper wrapper2 = new StandardWrapper();
wrapper2.setName("Modern");
wrapper2.setServletClass("ModernServlet");
Context context = new StandardContext();
// StandardContext's start method adds a default mapper
context.setPath("/app1");
context.setDocBase("app1");
context.addChild(wrapper1);
context.addChild(wrapper2);
LifecycleListener listener = new SimpleContextConfig();
((Lifecycle) context).addLifecycleListener(listener);
Host host = new StandardHost();
host.addChild(context);
host.setName("localhost");
host.setAppBase("webapps");
Loader loader = new WebappLoader();
context.setLoader(loader);
// context.addServletMapping(pattern, name);
context.addServletMapping("/Primitive", "Primitive");
context.addServletMapping("/Modern", "Modern");
Engine engine = new StandardEngine();
engine.addChild(host);
engine.setDefaultHost("localhost");
Service service = new StandardService();
service.setName("Stand-alone Service");
Server server = new StandardServer();
server.addService(service);
service.addConnector(connector);
// StandardService class's setContainer method calls
// its connectors' setContainer method
service.setContainer(engine);
// Start the new server
if (server instanceof Lifecycle) {
try {
server.initialize();
((Lifecycle) server).start();
server.await();
// the program waits until the await method returns,
// i.e. until a shutdown command is received.
}catch (LifecycleException e) {
e.printStackTrace(System.out);
}
}
// Shut down the server
if (server instanceof Lifecycle) {
try {
((Lifecycle) server).stop();
}catch (LifecycleException e) {
e.printStackTrace(System.out);
}
}
}
}
Bootstrap类的开始部分与第十三章的相似。创建了一个connector,两个wrapper,一个context,一个host和一个engine。之后将wrapper加到context中。然而其不将connector与顶层容器(engine)关联。main方法创建了一个Service对象,设置其名字,创建了一个server对象并添加service到server中。
Service service = new StandardService();
service.setName("Stand-alone Service");
Server server = new StandardServer();
server.addService(service);
main方法稍后将connector与engine添加到service中
service.addConnector(connector);
service.setContainer(engine);
通过添加connector给service,这个connector将与此service中的container关联。
main方法稍后调用server的initialize方法和start方法,从而初始化connector并启动connector与container。
if (server instanceof Lifecycle) {
try {
server.initialize();
((Lifecycle) server).start();
}
}
下一步,调用server的await方法,使server等待端口为8085的关闭命令。注意现阶段连接器已经运行,并等待默认端口的请求了。
server.await() ;
await方法直到接收到关闭命令后才会返回值。当这个发生的时候,main方法调用server的stop方法,最终停止所有的组件。
现在回顾一下Stopper类,停止服务。
the Stopper 类
在前面章节的应用程序中,要不是硬生生的停止或者按任一键。Stopper类提供了一种更优雅的方式来停止Catalina 服务。也保证了Lifecycle组件的stop方法都被调用。
package ex14.pyrmont.startup;
import java.io.OutputStream;
import java.io.IOException;
import java.net.Socket;
public class Stopper {
public static void main(String[] args) {
// the following code is taken from the Stop method of
// the org.apache.catalina.startup.Catalina class
int port = 8005;
try {
Socket socket = new Socket("127.0.0.1", port);
OutputStream stream = socket.getOutputStream();
String shutdown = "SHUTDOWN";
for (int i = 0; i < shutdown.length(); i++)
stream.write(shutdown.charAt(i));
stream.flush();
stream.close();
socket.close();
System.out.println("The server was successfully shut down.");
}
catch (IOException e) {
System.out.println("Error. The server has not been started.");
}
}
}
Stopper类的main方法创建了一个Socket对象,并稍后刷新了字符串SHUTDOWN,这是当前指定端口的关闭命令。如果Catalina正在运行,它将关闭。
Summary
这一章节解释了catalian中两个重要的组件:server和service。一个server相当有用,因为它提供了一种优雅的机制来开启和停止一个Catalina部署。一个service组件封装了一个container和一个或者多个connectors。这一章节的应用显示了如何使用server和service组件。也演示了如何在StandardServer类中使用关闭机制。