欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

程序员文章站 2022-06-23 13:39:53
我们的服务是部署在weblogic上的,最近遇到一个需求,需要在代码中获取weblogic部署当前服务的ip地址和端口。后来搜到一段代码,亲测有效:public static string getip...

我们的服务是部署在weblogic上的,最近遇到一个需求,需要在代码中获取weblogic部署当前服务的ip地址和端口。

后来搜到一段代码,亲测有效:

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;
	}	

可要理解这段代码后面的原理和思路,真是费劲了,需要了解以下知识:

jmx

jndi

rmi

ejb

总结成一句话就是,通过web应用通过weblogic提供的jndi访问weblogic的jmx中的对象。jndi后台用的技术就是ejb,而ejb是rmi在java语言上的实现。上述几个概念的具体含义,读者可以自行查询,网上资料很多。

下面回归正题,先从思路上详细分析下标题中的内容如何实现。

作为服务端代码,最后都是生成一个war放到服务器上去运行的。那从代码本身的程序来说,是肯定无法知道自己会被放到什么类型的web容器中、自己可以被访问的ip地址和端口号的。那谁知道的呢?只有web容器知道。换句话说,从这次要解决的问题上看,只有weblogic自己知道在其内部部署的应用被放到了哪个ip下,端口是多少。也就是说,解决这个问题的关键是,我们的服务程序如何去“问”weblogic容器,自己的ip和端口是多少。

好的,我们继续来想这个问题。能不能从weblogic容器中获取到服务的ip和端口号,取决于weblogic愿不愿意把这些信息开放给你,换句话说,取决于weblogic是否对外开放了可以获取其内部服务ip和端口的通道。

目前来看,必然是提供了的,查了weblogic的官网,发现了这样一段说明:

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

文章的链接地址为(oracle的官方文档):

https://docs.oracle.com/cd/e13222_01/wls/docs81/jmx/overview.html

只要获取到weblogic的mbeanserver,然后从mbeanserver中取出对应的objectname的属性,就可以获取到ip和端口了。这里面提到了jmx和rmi的概念,不清楚的,可以从上文找博文链接查看。

有一点是比较好理解的,就是weblogic必定会把自己处在runtime的服务信息写入到mbeanserver,然后我们通过mbeanserver把这些信息拿出来就行了。至于为什么要有mbeanserver,又是和jmx相关,这里就不再赘述。现在的关键问题是,我们的本地程序,如何访问到weblogic的mbeanserver?答案是通过initialcontext的lookup函数,而lookup函数最终的访问方式是jndi。也就是说,我们最终是通过weblogic对外提供的jndi访问到weblogic的mbeanserver的。mbeanserver在两个程序(weblogic和服务程序)之间的传递是通过ejb的。

拿到weblogic的mbeanserver之后,如何获取程序的ip的端口呢?这个当然要看weblogic是怎么设置进去的。按照设置进去的规则取出来就可以了。那如何知道weblogic的设置规则呢?我们继续看weblogic的文档。

原文链接:

https://docs.oracle.com/cd/e13222_01/wls/docs90/jmx/understandwls.html

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

发现了什么问题,红框中的文字,不就是刚才样例代码中的文字吗?再来看下面这段代码,通过本地程序访问runtime mbean server

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

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本地,那么通过jndi访问runtime mbean server的名称为java:comp/env/jmx/runtime。

runtime mbean server是mbeanserver的一种,通过下面的说明可以看到:

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

所以可以把runtime mbean server赋值给mbeanserver.

好,下一步,我们继续来调查,从runtime mbean server中如何取到端口和ip。通过以下代码获取runtimeservermbean的serverruntime属性。

        objectname tobjectname = new objectname(
                "com.bea:name=runtimeservice,type=weblogic.management.mbeanservers.runtime.runtimeservicembean");
        objectname serverrt = (objectname) tmbeanserver.getattribute(tobjectname, "serverruntime");

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

点开serverruntime属性,看看它还有什么二级属性,果然:

通过weblogic API解析如何获取weblogic中服务的IP和端口操作

listenport和listenaddress就是serverruntime的二级属性。通过以下代码获取到:

		string port = string.valueof(tmbeanserver.getattribute(serverrt, "listenport"));
		string listenaddr = (string) tmbeanserver.getattribute(serverrt, "listenaddress");

至此,所有代码解析完毕。

但是仔细想想,这段代码其实是有瑕疵的。换句话说,健壮性还不够。如果我们用的web容器不是weblogic怎么办?那代码岂不是就不管用了。所以我建议,完善下这段代码,增加对web容器的判断。其他web容器中如果获取ip和端口,还请读者自己探索。先通过下面的函数判断下当前的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需要对应jar包,利用maven引入的配置为:

<dependency>
		    <groupid>com.liferay.portal</groupid>
		    <artifactid>portal-kernel</artifactid>
		    <version>5.2.3</version>
		    <scope>provided</scope>
 
</dependency>

遇到问题,一定要多探索,与其看别人的博文,不如自己深入研究api,找样例代码。用一手资料。以上为个人经验,希望能给大家一个参考,也希望大家多多支持。