Tomcat中的服务器组件和 服务组件

  开始学习Tocmat时,都是学习如何通过实例化一个连接器 和 容器 来获得一个Servlet容器,并将连接器  和 servlet容器相互关联,但是之前学习的都只有一个连接器可以使用,该连接器服务8080端口上的HTTP请求,无法添加另一个连接器来服务 诸如 HTTPS之类的其他请求,而且前面所有学的示例,都缺少一种启动或者 关闭servlet容器的机制,那么下面学习一下提供这两种机制的特性的组件,分别是服务器组件 和 服务组件。

  服务器组件.

  org.apahce.catalina.Server接口的实例 表示Catalina的整个Servlet引擎,囊括了所有的组件,服务器组件是非常有用的,因为它使用了一种方法很容易的就启动/关闭整个系统,不需要对连接器 和 servlet容器 分别操作。

下面来说明一下启动/关闭机制的具体工作原理,当启动服务器组件是,它会启动它囊括的所有组件,然后它就无期限的等待关闭命令,如果想要关闭系统,可以向指定的端口发送一条关闭命令,服务器组件接收到关闭命令之后,就会关闭其中所有的组件。

  服务器组件使用了另一个组件(即服务组件)来包含其他组件,如一个容器组件 和 一个或者多个连接器组件,

下面先来看一下服务器组件的接口定义

  1 package org.apache.catalina;
  2
  3 import org.apache.catalina.deploy.NamingResources;
  4
  5 /**
  6  *
  7  * <p>
  8  * <b>Title:Server.java</b>
  9  * </p>
 10  * <p>
 11  * Copyright:ChenDong 2018
 12  * </p>
 13  * <p>
 14  * Company:仅学习时使用
 15  * </p>
 16  * <p>
 17  * 类功能描述:Server元素表示整个Catalina
 18  * servlet容器。它的属性代表了servlet容器的整体特性。服务器可以包含一个或多个服务以及顶级命名资源集。
 19  *
 20  *
 21  *
 22  * 通常,该接口的实现还将实现生命周期,这样当调用start()和stop()方法时,所有定义的服务也会启动或停止。
 23  *
 24  *
 25  *
 26  * 在这两者之间,实现必须打开端口属性指定的端口号上的服务器套接字。当接受连接时,读取第一行并与指定的关闭命令进行比较。如果命令匹配,则启动服务器关闭。
 27  * </p>
 28  *
 29  * @author
 30  * @date 2018年12月17日 下午8:04:51
 31  * @version 1.0
 32  */
 33
 34 public interface Server {
 35
 36     // ------------------------------------------------------------- Properties
 37
 38     /**
 39      *
 40      *
 41      * <p>
 42      * Title: getInfo
 43      * </p>
 44      *
 45      * @date 2018年12月17日 下午8:05:15
 46      *
 47      *       <p>
 48      *       功能描述:返回该类的实现信息
 49      *       </p>
 50      *
 51      * @return
 52      */
 53     public String getInfo();
 54
 55     /**
 56      * 返回全局命名资源。
 57      */
 58     public NamingResources getGlobalNamingResources();
 59
 60     /**
 61      *
 62      * 设置全局命名资源
 63      *
 64      * @param namingResources
 65      *            新的全局命名资源
 66      */
 67     public void setGlobalNamingResources(NamingResources globalNamingResources);
 68
 69     /**
 70      *
 71      *
 72      * <p>
 73      * Title: getPort
 74      * </p>
 75      *
 76      * @date 2018年12月17日 下午8:06:42
 77      *
 78      *       <p>
 79      *       功能描述:返回我们用来监听关闭命令的端口号
 80      *       </p>
 81      *
 82      * @return
 83      */
 84     public int getPort();
 85
 86     /**
 87      *
 88      *
 89      * <p>
 90      * Title: setPort
 91      * </p>
 92      *
 93      * @date 2018年12月17日 下午8:07:27
 94      *
 95      *       <p>
 96      *       功能描述:设置我们用来监听关闭命令的端口号
 97      *       </p>
 98      *
 99      * @param port
100      *            新的监听端口号
101      */
102     public void setPort(int port);
103
104     /**
105      * 返回我们正在等待的关闭命令字符串。
106      *
107      *
108      */
109     public String getShutdown();
110
111     /**
112      * 设置我们正在等待的关闭命令字符串
113      *
114      * @param shutdown
115      *            新的关闭命令字符串
116      */
117     public void setShutdown(String shutdown);
118
119     // --------------------------------------------------------- Public Methods
120
121     /**
122      * 向定义的服务集添加新服务。
123      *
124      * @param service
125      *            要被添加的新服务
126      */
127     public void addService(Service service);
128
129     /**
130      * 等待直到收到正确的关闭命令,然后返回。
131      */
132     public void await();
133
134     /**
135      *
136      *
137      * <p>
138      * Title: findService
139      * </p>
140      *
141      * @date 2018年12月17日 下午8:10:42
142      *
143      *       <p>
144      *       功能描述:返回指定的服务(如果存在);否则返回<code>null</code>
145      *       </p>
146      *
147      * @param name
148      * @return
149      */
150     public Service findService(String name);
151
152     /**
153      *
154      *
155      * <p>
156      * Title: findServices
157      * </p>
158      *
159      * @date 2018年12月17日 下午8:11:18
160      *
161      *       <p>
162      *       功能描述:返回在此服务器中定义的服务集。
163      *       </p>
164      *
165      * @return
166      */
167     public Service[] findServices();
168
169     /**
170      *
171      *
172      * <p>
173      * Title: removeService
174      * </p>
175      *
176      * @date 2018年12月17日 下午8:12:02
177      *
178      *       <p>
179      *       功能描述:从该服务器 定义的服务集中删除指定的服务
180      *       </p>
181      *
182      * @param service
183      */
184     public void removeService(Service service);
185
186     /**
187      *
188      *
189      * <p>
190      * Title: initialize
191      * </p>
192      *
193      * @date 2018年12月17日 下午8:12:58
194      *
195      *       <p>
196      *       功能描述:调用启动前的初始化。这用于允许连接器绑定到Unix操作环境中的受限端口。当然只要是在系统执行前 你爱写啥写啥
197      *       </p>
198      *
199      * @throws LifecycleException
200      */
201     public void initialize() throws LifecycleException;
202 }

  shutdown属性保存了必须发送给Server实例用来关闭整个系统的关闭命令,port属性定义了服务器组件会从哪一个端口获取关闭命令,可以调用其addService方法为服务器组件添加服务组件,或者通过removeService方法来删除某个服务组件,findService方法返回添加到此服务器组件中的服务集合,initialize方法包含了在系统启动之前要执行的一些代码

  在Catalina中 server同样有其标准实现类,StandardServer

StandardServer类

  org.apahce.catalina.core.StandardServer类是Server接口的标准实现,为什么要说下这个类,主要是对其中的关闭机制 也就上文提到的一个关闭所有组件的机制感兴趣,而这也是这个类最重要的特性,该类中的许多方法都与新server.xml文件中的服务器配置的存储相关,但这些并不是下面要说的重点,

  一个服务器组件可以有0个或者多个服务组件,StandardServer类提供了addService方法、removeService方法、和findService方法的实现。

  StandardServer类有四个与生命周期相关的方法,分别是initialize方法、start方法、stop方法,就像其他组件一样,可以初始化并且启动服务器组件。也可以调用 await方法 和 stop方法,调用await方法会一直阻塞住,直到它从定义 的 8005;端口(也可以自己配置其他端口)上接收到关闭命令,当await方法返回的时候,会运行stop方法来关闭其下的所有服务组件。

下面会分别讨论上面的 四个与生命周期相关的方法。

initialize方法

  方法主要是用于初始化添加到StandardServer的服务组件,

 1 /**
 2      * 调用启动前的初始化。
 3      */
 4     public void initialize() throws LifecycleException {
 5         if (initialized)
 6             throw new LifecycleException(sm.getString("standardServer.initialize.initialized"));
 7         initialized = true;
 8
 9         // 初始化我们定义的服务集中的每一个服务
10         for (int i = 0; i < services.length; i++) {
11             services[i].initialize();
12         }
13     }

start方法

  start方法用于启动服务器组件,在StandardServer类的start方法的实现中,它会启动器所有的服务组件,逐个启动所有的组件,如连接器组件 和 Servlet容器,

 1 /**
 2      * 该服务器组件的启动方法,它会启动器所有的服务组件,逐个启动所有的组件,
 3      */
 4
 5     public void start() throws LifecycleException {
 6
 7         // 验证和更新当前组件状态 如果已经启动直接报错
 8         if (started)
 9             throw new LifecycleException(sm.getString("standardServer.start.started"));
10         // 向监听器发送 BEFORE_START_EVENT事件 与 START_EVENT事件
11         lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
12
13         lifecycle.fireLifecycleEvent(START_EVENT, null);
14         started = true;
15
16         // 逐个启动当前定义的服务集合中的每一个服务
17         synchronized (services) {
18             for (int i = 0; i < services.length; i++) {
19                 if (services[i] instanceof Lifecycle)
20                     ((Lifecycle) services[i]).start();
21             }
22         }
23
24         // 向监听器发送 AFTER_START_EVENT事件
25         lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
26
27     }

StandardServer为了防止服务器组件重复启动,在start中设置为true 在stop方法中 重置为false。

stop方法

  stop方法用于关闭服务器组件,在方法中会关闭服务器中的额所有组件

 1     /**
 2      * 优雅地终止该组件的公共方法的主动使用。此方法应该是调用该组件的给定实例的最后一个方法。
 3      * 它还应该向任何注册的监听器发送STOP_EVENT类型的停止事
 4      */
 5     public void stop() throws LifecycleException {
 6
 7         // 如果还没有启动则 直接抛出错误
 8         if (!started)
 9             throw new LifecycleException(sm.getString("standardServer.stop.notStarted"));
10
11         // 向监听器发送监听事件
12         lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
13
14         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
15         // 将started标志 置为false 这样才可以再次启动
16         started = false;
17
18         // 逐个停止我们定义服务集中的每一个服务
19         for (int i = 0; i < services.length; i++) {
20             if (services[i] instanceof Lifecycle)
21                 ((Lifecycle) services[i]).stop();
22         }
23
24         // 发送监听事件
25         lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
26
27     }

调用stop方法hi关闭所有的服务组件并重置布尔变量started,这样才可以再次启动服务器组件。

await方法

  await方法负责等待关闭整个Tomcat部署的命令。

 1     /**
 2      * 等待直到收到正确的关闭命令,然后返回。
 3      */
 4     public void await() {
 5
 6         // 设置要等待的服务器套接字
 7         ServerSocket serverSocket = null;
 8         try {
 9             // 利用咱们自己定义的port(默认 8005 )端口号来 初始化服务器套接字
10             serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
11         } catch (IOException e) {
12             System.err.println("StandardServer.await: create[" + port + "]: " + e);
13             e.printStackTrace();
14             System.exit(1);
15         }
16
17         // 循环等待连接和有效命令
18         while (true) {
19
20             // 等待下一个连接
21             Socket socket = null;
22             InputStream stream = null;
23             try {
24                 socket = serverSocket.accept();//
25                 socket.setSoTimeout(10 * 1000); // 接收到Socket之后 read方法仅在十秒钟之内有效
26                                                 // 超时 将会抛出
27                                                 // java.net.SocketTimeoutException
28                 stream = socket.getInputStream();
29             } catch (AccessControlException ace) {
30                 System.err.println("StandardServer.accept security exception: " + ace.getMessage());
31                 continue;
32             } catch (IOException e) {
33                 System.err.println("StandardServer.await: accept: " + e);
34                 e.printStackTrace();
35                 System.exit(1);
36             }
37
38             // 从套接字中读取一组字符
39             StringBuffer command = new StringBuffer();
40             int expected = 1024; // 切断以避免DoS攻击
41             while (expected < shutdown.length()) {
42                 if (random == null)
43                     random = new Random(System.currentTimeMillis());
44                 expected += (random.nextInt() % 1024);
45             }
46             while (expected > 0) {
47                 int ch = -1;
48                 try {
49                     ch = stream.read();
50                 } catch (IOException e) {
51                     System.err.println("StandardServer.await: read: " + e);
52                     e.printStackTrace();
53                     ch = -1;
54                 }
55                 if (ch < 32) // 控制字符或EOF终止循环
56                     break;
57                 command.append((char) ch);
58                 expected--;
59             }
60
61             // 既然我们用完了,就把socket关上。
62             try {
63                 socket.close();
64             } catch (IOException e) {
65                 ;
66             }
67
68             // 匹配命令字符串
69             boolean match = command.toString().equals(shutdown);
70             if (match) {
71                 //匹配到就 跳出循环
72                 break;
73             } else
74                 System.err.println("StandardServer.await: Invalid command ‘" + command.toString() + "‘ received");
75
76         }
77
78         //关闭服务器套接字并返回
79         try {
80             serverSocket.close();
81         } catch (IOException e) {
82             ;
83         }
84
85     }

  await方法创建一个ServerSocket对象,监听8005端口,并在while循环中调用它的accpect方法挡在指定端口上接收到消息时,才会从accept方法中返回一个socket,然后将接收到的消息与关闭命令字符串做比较,相同的话就跳出循环,关闭ServerSocke,否则再次循环。接续等待消息。

小累  休息休息 早点睡觉 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,

原文地址:https://www.cnblogs.com/ChenD/p/Tomcat-Server-StandardServer.html

时间: 2024-10-10 12:10:28

Tomcat中的服务器组件和 服务组件的相关文章

tomcat(14)服务器组件和服务组件

[0]README 0.1)本文部分文字描述转自 "how tomcat works",旨在学习 "tomcat(14)服务器组件和服务组件" 的基础知识: 0.2)for complete source code ,please visit  https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter14 [1]服务器组件(org.apache.catalina.Server) 1)org.a

How tomcat works 读书笔记十四 服务器组件和服务组件

之前的项目还是有些问题的,例如 1 只能有一个连接器,只能处理http请求,无法添加另外一个连接器用来处理https. 2 对容器的关闭只能是粗暴的关闭Bootstrap. 服务器组件 org.apache.catalina.Server接口的实例用来表示Catalina的整个servlet引擎. 我们使用Server就是因为,它用一种优雅的方式来启动/关闭整个系统. 下面是启动和停止机制是如何工作的.当服务器启动的时候,它启动它内部的所有组件.然后无限期的等待关闭命令,如果你想要关闭系统,发送

Tomcat中部署web应用 ---- Dubbo服务消费者Web应用war包的部署

IP:192.168.2.61 部署容器:apache-tomcat-7.0.57 端口:8080 应用:edu-web-boss.war 1.下载(或上传)最新版的Tomcat7: $wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-7/v7.0.57/bin/apache-tomcat-7.0.57.tar.gz 2.规范安装目录: /home/wusc/edu/web/xxx-tomcat 如: /home/wusc/edu/web/

使用Tomcat中的start.bat启动服务,配置jdk的路径

为什么要在setclasspath.bat设置JAVA_HOME和JRE_HOME的变量的值? 在windows环境下以批处理文件方式启动tomcat,只要运行<CATALINA_HOME>/bin/startup.bat这个文件,就可以启动Tomcat.在启动时,startup.bat会调用catalina.bat文件,而catalina.bat会调用setclasspath.bat文件来获取JAVA_HOME和JRE_HOME这两个环境变量的值,因此若要在tomcat启动时指向特定的JDK

Tomcat系列之服务器的安装与配置以及各组件详解

Tomcat系列之服务器的安装与配置以及各组件详解 大纲 一.前言 二.安装与配置Tomcat 三.Tomcat 目录的结构 四.Tomcat 配置文件 注,本文的测试的操作系统为CentOS 6.4 x86_64,软件版本为jdk-7u40.apache-tomcat-7.0.42.博文中的所有软件请到这里下载:http://yunpan.cn/QGBCLwrZnpLMS. 一.前言 在上一篇博文中我们主要讲解的Tomcat的基础知识以及相关的Java知识,对于不怎么清楚的博友可以参考一下:h

Tomcat中日志组件

Tomcat日志组件 AccessLog接口 public interface AccessLog { public void log(Request request, Response response, long time); } AccessLogAdapter public class AccessLogAdapter implements AccessLog { private AccessLog[] logs; // 构造函数 public AccessLogAdapter(Acce

Tomcat结构、启动过程、关键组件简单分析

Tomcat 结构: Tomcat最顶层容器叫Server,代表整个服务器,Server中包含至少一个Service,用于具体提供服务,Service主要包含:Connector和Container,前者处理链接并提供Socket与request和response的转换,Container用于封装和管理Servlet,以及具体处理request请求. 一个Tomcat里一个Server,包含多个Service,一个Service只有一个Container,可以有多个Connector.一个Con

1.4 主要组件与服务

1.4  主要组件与服务 SQL Server 不仅仅是数据库的概念,除了提供数据库引擎之外,还有一套完整的商业智能解决方案.商业智能还需要使用 SQL Server 的另外三个服务:集成服务(SQL Server Integration Services,简称 SSIS).分析服务(SQL Server Analysis Services,简称 SSAS).报表服务(SQL Server Reporting Services,简称 SSRS). 1.4.1  实例 实例可以看作是 SQL Se

Hortonworks HDP Sandbox定制(配置)开机启动服务(组件)

定制Hortonworks HDP开机启动服务可以这样做:本文原文出处: http://blog.csdn.net/bluishglc/article/details/42109253 严禁任何形式的转载,否则将委托CSDN官方维护权益! 找到文件:/usr/lib/hue/tools/start_scripts/start_deps.mf,Hortonworks HDP启动所有服务和组件的命令都在这个文件中,之所以把这些服务的启动命令写在了一个makefile中而不是一个shell文件,其实就