Undertow是紅帽公司開發的一款基於 NIO 的高性能 Web 嵌入式服務器。springboot也將Undertow作爲可選的內嵌容器,爲其提供支持。
作爲公司的中間支撐團隊,我們爲其他團隊提供了一些通用功能的jar包,比如統一的日誌採集和jvm指標監控等,其中有一些需要獲取到java應用的端口。而最近有一個業務團隊將springboot中的容器換成了undertow,原本的獲取端口的工具類只支持tomcat,需要進行升級來支持undertow容器。
獲取端口的一些問題:
首先,在spring項目中獲取端口最常見的方式,應該是繼承ApplicationListener
類,來監聽spring項目啓動過程中的Event,並使用event.getEmbeddedServletContainer().getPort()
來獲取端口號。
但是我們提供出去的jar包,需要儘量減少對別人項目的侵入性,因此不能實例化Listener來監聽事件,只能使用一些靜態方法來實現此功能。
這邊我們參照tomcat獲取端口的方法,最後採用的方法是:
使用MBean獲取容器信息
MBean是一個被管理的Java對象,就像Javabean組件一樣,但是它遵從JMX規範的設計模式。MBean可以表示設備、應用或者任何需要被管理的資源。
Undertow註冊的MBean節點信息,其中包含了監聽端口:
獲取端口的代碼:
通過查詢MBean,來獲取Undertow的端口信息
public static int getUndertowPort() throws MalformedObjectNameException {
// 通過Query匹配查詢,找到含有端口信息的節點
String keyProp = ManagementFactory.getPlatformMBeanServer()
.queryNames(new ObjectName("*:type=Xnio,*"), Query.match(Query.attr("BindAddress"), Query.value("*:*")))
.iterator().next().getKeyProperty("address");
// 從節點中取出端口信息
keyProp = keyProp.replace("\"", "");
String portStr = keyProp.substring(keyProp.lastIndexOf(":") + 1);
return Integer.valueOf(portStr);
}
一般框架或容器都會將一些數據通過MBean的形式暴露出去,因此我們可以通過類似上面的方法,獲取一些運行時數據。