通過(guò)weblogic API解析如何獲取weblogic中服務(wù)的IP和端口操作
我們的服務(wù)是部署在weblogic上的,最近遇到一個(gè)需求,需要在代碼中獲取weblogic部署當(dāng)前服務(wù)的IP地址和端口。
后來(lái)搜到一段代碼,親測(cè)有效:
public static String getIpAndPort(){ try { InitialContext initialContext = new InitialContext(); MBeanServer tMBeanServer; MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); tMBeanServer = (MBeanServer) initialContext.lookup("java:comp/env/jmx/runtime"); ObjectName tObjectName = new ObjectName( "com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean"); ObjectName serverrt = (ObjectName) tMBeanServer.getAttribute(tObjectName, "ServerRuntime"); String port = String.valueOf(tMBeanServer.getAttribute(serverrt, "ListenPort")); String listenAddr = (String) tMBeanServer.getAttribute(serverrt, "ListenAddress"); String[] tempAddr = listenAddr.split("/"); if (tempAddr.length == 1) { listenAddr = tempAddr[0]; } else if (tempAddr[tempAddr.length - 1].trim().length() != 0) { listenAddr = tempAddr[tempAddr.length - 1]; } else if (tempAddr.length > 2) { listenAddr = tempAddr[tempAddr.length - 2]; } StringBuilder sBuilder = new StringBuilder(listenAddr); sBuilder.append(":"); sBuilder.append(port); System.out.print(sBuilder); return sBuilder.toString(); } catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedObjectNameException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstanceNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (AttributeNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ReflectionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MBeanException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
可要理解這段代碼后面的原理和思路,真是費(fèi)勁了,需要了解以下知識(shí):
JMX
JNDI
RMI
EJB
總結(jié)成一句話就是,通過(guò)web應(yīng)用通過(guò)weblogic提供的JNDI訪問(wèn)weblogic的JMX中的對(duì)象。JNDI后臺(tái)用的技術(shù)就是EJB,而EJB是RMI在java語(yǔ)言上的實(shí)現(xiàn)。上述幾個(gè)概念的具體含義,讀者可以自行查詢,網(wǎng)上資料很多。
下面回歸正題,先從思路上詳細(xì)分析下標(biāo)題中的內(nèi)容如何實(shí)現(xiàn)。
作為服務(wù)端代碼,最后都是生成一個(gè)war放到服務(wù)器上去運(yùn)行的。那從代碼本身的程序來(lái)說(shuō),是肯定無(wú)法知道自己會(huì)被放到什么類型的web容器中、自己可以被訪問(wèn)的IP地址和端口號(hào)的。那誰(shuí)知道的呢?只有web容器知道。換句話說(shuō),從這次要解決的問(wèn)題上看,只有weblogic自己知道在其內(nèi)部部署的應(yīng)用被放到了哪個(gè)IP下,端口是多少。也就是說(shuō),解決這個(gè)問(wèn)題的關(guān)鍵是,我們的服務(wù)程序如何去“問(wèn)”weblogic容器,自己的IP和端口是多少。
好的,我們繼續(xù)來(lái)想這個(gè)問(wèn)題。能不能從weblogic容器中獲取到服務(wù)的IP和端口號(hào),取決于weblogic愿不愿意把這些信息開放給你,換句話說(shuō),取決于weblogic是否對(duì)外開放了可以獲取其內(nèi)部服務(wù)IP和端口的通道。
目前來(lái)看,必然是提供了的,查了weblogic的官網(wǎng),發(fā)現(xiàn)了這樣一段說(shuō)明:
文章的鏈接地址為(oracle的官方文檔):
https://docs.oracle.com/cd/E13222_01/wls/docs81/jmx/overview.html
只要獲取到weblogic的MBeanServer,然后從MBeanServer中取出對(duì)應(yīng)的ObjectName的屬性,就可以獲取到IP和端口了。這里面提到了JMX和RMI的概念,不清楚的,可以從上文找博文鏈接查看。
有一點(diǎn)是比較好理解的,就是weblogic必定會(huì)把自己處在runtime的服務(wù)信息寫入到MBeanServer,然后我們通過(guò)MBeanServer把這些信息拿出來(lái)就行了。至于為什么要有MBeanServer,又是和JMX相關(guān),這里就不再贅述?,F(xiàn)在的關(guān)鍵問(wèn)題是,我們的本地程序,如何訪問(wèn)到weblogic的MBeanServer?答案是通過(guò)InitialContext的lookup函數(shù),而lookup函數(shù)最終的訪問(wèn)方式是JNDI。也就是說(shuō),我們最終是通過(guò)weblogic對(duì)外提供的JNDI訪問(wèn)到weblogic的MBeanServer的。MBeanServer在兩個(gè)程序(weblogic和服務(wù)程序)之間的傳遞是通過(guò)EJB的。
拿到weblogic的MBeanServer之后,如何獲取程序的IP的端口呢?這個(gè)當(dāng)然要看weblogic是怎么設(shè)置進(jìn)去的。按照設(shè)置進(jìn)去的規(guī)則取出來(lái)就可以了。那如何知道weblogic的設(shè)置規(guī)則呢?我們繼續(xù)看weblogic的文檔。
原文鏈接:
https://docs.oracle.com/cd/E13222_01/wls/docs90/jmx/understandWLS.html
發(fā)現(xiàn)了什么問(wèn)題,紅框中的文字,不就是剛才樣例代碼中的文字嗎?再來(lái)看下面這段代碼,通過(guò)本地程序訪問(wèn)Runtime MBean Server
If the classes for the JMX client are located in a J2EE module, such as an EJB or Web application, then the JNDI name for the Runtime MBeanServer is:
java:comp/env/jmx/runtime
翻譯下,如果JMX客戶端(EJB或者Web程序)在J2EE本地,那么通過(guò)JNDI訪問(wèn)Runtime MBean Server的名稱為java:comp/env/jmx/runtime。
Runtime MBean Server是MBeanServer的一種,通過(guò)下面的說(shuō)明可以看到:
所以可以把Runtime MBean Server賦值給MBeanServer.
好,下一步,我們繼續(xù)來(lái)調(diào)查,從Runtime MBean Server中如何取到端口和IP。通過(guò)以下代碼獲取RuntimeServerMBean的ServerRuntime屬性。
ObjectName tObjectName = new ObjectName( "com.bea:Name=RuntimeService,Type=weblogic.management.mbeanservers.runtime.RuntimeServiceMBean"); ObjectName serverrt = (ObjectName) tMBeanServer.getAttribute(tObjectName, "ServerRuntime");
點(diǎn)開ServerRuntime屬性,看看它還有什么二級(jí)屬性,果然:
ListenPort和ListenAddress就是ServerRuntime的二級(jí)屬性。通過(guò)以下代碼獲取到:
String port = String.valueOf(tMBeanServer.getAttribute(serverrt, "ListenPort")); String listenAddr = (String) tMBeanServer.getAttribute(serverrt, "ListenAddress");
至此,所有代碼解析完畢。
但是仔細(xì)想想,這段代碼其實(shí)是有瑕疵的。換句話說(shuō),健壯性還不夠。如果我們用的web容器不是weblogic怎么辦?那代碼豈不是就不管用了。所以我建議,完善下這段代碼,增加對(duì)web容器的判斷。其他web容器中如果獲取IP和端口,還請(qǐng)讀者自己探索。先通過(guò)下面的函數(shù)判斷下當(dāng)前的web容器:
public static String getServerName() { String serverName = null; if (ServerDetector.isWebLogic()) { serverName = "WebLogic"; } else if (ServerDetector.isTomcat()) { serverName = "Tomcat"; } else if (ServerDetector.isWebSphere()) { serverName = "WebSphere"; } else if (ServerDetector.isSupportsComet()) { serverName = "SupportsComet"; } else if (ServerDetector.isResin()) { serverName = "Resin"; } else if (ServerDetector.isOC4J()) { serverName = "OC4J"; } else if (ServerDetector.isJOnAS()) { serverName = "JOnAS"; } else if (ServerDetector.isJetty()) { serverName = "Jetty"; } else if (ServerDetector.isJBoss()) { serverName = "JBoss"; } else if (ServerDetector.isGeronimo()) { serverName = "Geronimo"; } else if (ServerDetector.isGlassfish()) { serverName = "Glassfish"; } else if (ServerDetector.isGlassfish2()) { serverName = "Glassfish2"; } else if (ServerDetector.isGlassfish3()) { serverName = "Glassfish3"; } return serverName; }
ServerDetector需要對(duì)應(yīng)jar包,利用maven引入的配置為:
<dependency> <groupId>com.liferay.portal</groupId> <artifactId>portal-kernel</artifactId> <version>5.2.3</version> <scope>provided</scope> </dependency>
遇到問(wèn)題,一定要多探索,與其看別人的博文,不如自己深入研究API,找樣例代碼。用一手資料。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)和算法學(xué)習(xí)之漢諾塔示例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)和算法中的漢諾塔示例,需要的朋友可以參考下2014-02-02Spring開發(fā)核心之AOP的實(shí)現(xiàn)與切入點(diǎn)持久化
面向?qū)ο缶幊淌且环N編程方式,此編程方式的落地需要使用“類”和 “對(duì)象”來(lái)實(shí)現(xiàn),所以,面向?qū)ο缶幊唐鋵?shí)就是對(duì) “類”和“對(duì)象” 的使用,面向切面編程,簡(jiǎn)單的說(shuō),就是動(dòng)態(tài)地將代碼切入到類的指定方法、指定位置上的編程思想就是面向切面的編程2022-10-10Idea Jrebel 報(bào)錯(cuò):Cannot reactivate,offline 
本文主要介紹了Idea Jrebel 報(bào)錯(cuò):Cannot reactivate,offline seat in use,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Spring Data MongoDB 數(shù)據(jù)庫(kù)批量操作的方法
在項(xiàng)目開發(fā)中經(jīng)常會(huì)批量插入數(shù)據(jù)和更新數(shù)據(jù)的操作,這篇文章主要介紹了Spring Data MongoDB 數(shù)據(jù)庫(kù)批量操作的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-11-11