创建嵌入式Tomcat服务器

1.创建嵌入式Tomcat服务器

1.1 将Tomcat嵌入到 Java应用

为了将Tomcat服务器嵌入到 Java应用中,需要用到Tomcat API中的一些类,最主要的一个类是 org.apache.catalina.startup.Tomcat类。Tomcat类的主要方法描述见下表,也可以参考Tomcat的API文档,网址为:http://tomcat.apache.org/tomcat-9.0-doc/api/index.html

方法 描述
setBaseDir 设置Tomcat服务器的跟路径
getServer 返回Server对象。如果Server不存在,就创建一个标准的Server,并将它返回
getEngine 返回Engine对象。如果Engine不存在,就创建一个标准的Engine,并将它返回
getHost 返回Host对象。如果Host不存在,就创建一个标准的Host,并将它返回
getConnector 返回HTTP Connector对象。如果Connector不存在,就创建一个默认的Connector,并将它返回
addWebapp 把一个Web应用加入到Tomcat的服务器中
start 启动Tomcat服务器
stop 停止Tomcat服务器

默认情况下,这些组件在server.xml文件中进行配置。如果把Tomcat嵌入到Java应用中,这个配置文件就无用了,所以必须通过程序来配置这些组件的实例。

  • 顶层类组件:Server和Service
  • 容器类组件:Engine、Host和Context
  • 连接器:Connector

Tomcat类的start()的方法负责启动Tomcat服务器,它会先调用 getServer()方法:

public void start() throws LifecycleException {
	getServer();
	server.start();
}

Tomcat类的getServer()方法返回Server对象,如果Server对象不存在,会创建标准的 Server对象和 Service对象,然后将再让他们返回:

public Server getServer() {
	if (server != null) {
        return server;
    }
    
    System.setProperty("catalina.userNaming", "false");
    server = new StandardServer();
    initBaseDir();
    server.setPort(-1);
    Service service = new StandardService();
    service.setName("Tomcat");
    server.addService(service);
    return server;
}

Tomcat类的addWebapp()方法责把一个Web应用加入到Tomcat服务器中,并且返回相应的Context对象。addWebapp()方法有多种重载形式,这些重载形式的addWebapp()方法会先调用getHost()方法,确保Host对象已经创建:

public Context addWebapp(Host host, String contextPath, String docBase) {
    LifecycleListener listener = null;
    try{
        Class<?> clazz = Class.forName(getHost().getConfigClass());
        listener = (LifecycleListener) clazz.getConstructor().newInstance();
    } catch (ReflectiveOperationException e) {
        throw new IllegalArgumentException(e);
    }
    return addWebapp(host, contextPath, docBase, listener);
}

而Tomcat类的 getHost()方法会先调用的 getEngine()方法,确保Engine对象已经创建。并且如果Host不存在,会创建标准的Host对象:

publicf Host getHost() {
    Engine engine = getEngine();
    if (engine.findChildren().length > 0) {
        return (Host) engine.findChildren()[0];
    }
    
    Host host = new StandardHost();
    host.setName(hostname);
    getEngine().addChild(host);
    return host;
}

1.2 创建嵌入了 Tomcat的Java示范程序

下面创建一个EmbeddedTomcat类,在该程序中创建了一个嵌入式 Tomcat服务器,并且加入了一个默认的Web应用,以及examples应用和docs应用。

import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;

public class EmbeddedTomcat {
    
  private Tomcat tomcat;
    
  public void start(int port,String baseDir) throws LifecycleException {

    tomcat = new Tomcat();
       
    //设置服务器以及虚拟主机的根路径
    tomcat.setBaseDir(".");
   
    tomcat.getHost().setAppBase(baseDir); 
    
    //设置监听端口
    tomcat.setPort(port);
    
    //获得连接器,如果还没有连接器,就会先创建一个默认的连接器
    Connector connector=tomcat.getConnector();
       
    //加入默认的web应用         
    Context context1=tomcat.addWebapp("", baseDir+"/ROOT");

    //加入examples应用
    Context context2=tomcat.addWebapp("/examples", baseDir+"/examples");

    //加入docs应用
    Context context3=tomcat.addWebapp("/docs", baseDir+"/docs");
 
    tomcat.start();
  //启动服务器(启动后台线程)

   
   //终止服务器的办法一:主线程调用Tomcat类的stop()方法
   /*
    try{
      //主线程睡眠60*60秒后关闭服务器
      Thread.sleep(60000*60);
      stop();  
    }catch(Exception e){e.printStackTrace();} 
   */

    //终止服务器的办法二:监听8005端口的SHUTDOWN命令

    StandardServer server = (StandardServer) tomcat.getServer();
   
    //设置服务器监听SHUTDOWN命令的端口
    server.setPort(8005);
    server.await();  //主线程进入等待状态,直到接收到SHUTDOWN命令

  }
   

  public void stop() throws LifecycleException {
        
    tomcat.stop();
  //关闭Tomcat服务器 
  } 
    

  public static void main(String[] args) {
        
    try{
            
      int port=8080;
           
      String baseDir = "C:/tomcat/webapps";
           
      EmbeddedTomcat tomcat = new EmbeddedTomcat();
           
      tomcat.start(port, baseDir);
           
    }catch (Exception e) {
e.printStackTrace();
 }
   
  } 

}

分析上述代码:

  1. 创建Tomcat对象,并且设置它的根路径,接收HTTP请求使用的端口号,以及他的虚拟主机的根路径:

    tomcat = new Tomcat();
    
    //设置服务器以及虚拟主机的根路径
    tomcat.setBaseDir(".");
    
    tomcat.getHost().setAppBase(baseDir); 
    
    //设置监听端口
    tomcat.setPort(port);
    
  2. 通过Tomcat的对象的getConnector()方法创建并返回默认的HTTP Connector连接器。在Tomcat9以前的版本中,这不是必须的步骤。而在Tomcat9中,这个步骤是必须的,他确保创建默认的连接器,:

    Connector connector=tomcat.getConnector();
    
  3. 向Tomcat的服务器中加入Web应用:

    //加入默认的web应用         
    Context context1=tomcat.addWebapp("", baseDir+"/ROOT");
    
    //加入examples应用
    Context context2=tomcat.addWebapp("/examples", baseDir+"/examples");
    
    //加入docs应用
    Context context3=tomcat.addWebapp("/docs", baseDir+"/docs");
    

    Tomcat类的 addWebapp(String contextPath, String docBase) 方法的第一个参数 contextPath 指定访问Web应用的 URL入口。当 contextPath 参数的值为"",表示虚拟主机的默认Web应用,第二个参数docBase指定 Web应用所在的文件路径的根路径。访问以上三个Web应用的URL分别为:

    http://localhost:8080
    http://localhost:8080/examples
    http://localhost:8080/docs
    
  4. 启动Tomcat服务,main 主线程进入等待状态:

        tomcat.start();  //启动服务器(启动后台线程)
    
        StandardServer server = (StandardServer) tomcat.getServer();
       
        //设置服务器监听SHUTDOWN命令的端口
        server.setPort(8005);
        server.await();  //main主线程进入等待状态,直到接收到SHUTDOWN命令,就会终止服务器
    

    tomcat.start()方法启动Tomcat的服务器,该服务器启动工作线程池来响应客户端的HTTP请求。线程池中的工作线程为后台线程。所谓后台线程,是指它的生命周期依赖于 main主线程。只要主线程未结束生命周期,后台线程也会一直运行,当主线程结束生命周期,后台线程也会自动结束生命周期。

1.3 终止嵌入式Tomcat服务器

有两种办法。

  • 调用Tomcat类的stop()方法。
  • 向8005端口发送 “SHUTDOWN” 命令。

1.3.1 通过 SHUTDOWN 命令终止服务器

下面创建一个TomcatManager类,他利用 Socket向8005端发送 “SHUTDOWN” 命令,从而终止服务器。

import java.net.*;
import java.io.*;
import java.util.*;

public class TomcatManager {
  public static void main(String args[]){
    Socket socket=null;
    String host="localhost";
    int port=8005;
    
    try{
      socket=new Socket(host,port); //与Tomcat建立FTP连接
    }catch(Exception e){e.printStackTrace();}
  
    try{
      String command="SHUTDOWN";
      /*发送HTTP请求*/
      OutputStream socketOut=socket.getOutputStream();//获得输出流  
      socketOut.write(command.getBytes());
    
      Thread.sleep(2000); //睡眠2秒
    
      System.out.println("已经发送SHUTDOWN命令"); 
      
    }catch(Exception e){ 
      e.printStackTrace();
    }finally{
      try{
        socket.close();  
      }catch(Exception e){e.printStackTrace();}
    }
  } 
}

1.4 运行嵌入式Tomcat服务器

编译和运行本范例程序时,应该到官方网站下载与嵌入式Tomcat服务器相关的类库,下载得到的文件为apache-tomcat-X-embed.zip,解压这个文件,把其中所有的 JAR文件加入到 lib目录中。

你可能感兴趣的:(tomcat,服务器,java)