在没有请求的情况下从tomcat获取服务器端口号

是否有任何Tomcat API或配置可以告诉应用程序(可能在启动时),它运行的端口没有请求?

想象一下,有两个Web应用程序在同一个Tomcat中运行,其中一个需要从另一个调用Web服务。 我们不希望请求离开Tomcat(如果您使用Apache服务器名称或绝对URL,请求将出去并再次返回并且它可以转到任何实例)并返回。为此,我知道机器名称但无法获取端口号。 我知道我可以硬编码这些信息,但我不想这样做,因为我希望我的war文件与应用程序服务器无关。

我知道如果我们有HTTPServletRequest,我们可以找到它

这仅适用于Tomcat 6,不适用于Tomcat 7

有了这个:

 List getEndPoints() throws MalformedObjectNameException, NullPointerException, UnknownHostException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); QueryExp subQuery1 = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")); QueryExp subQuery2 = Query.anySubString(Query.attr("protocol"), Query.value("Http11")); QueryExp query = Query.or(subQuery1, subQuery2); Set objs = mbs.queryNames(new ObjectName("*:type=Connector,*"), query); String hostname = InetAddress.getLocalHost().getHostName(); InetAddress[] addresses = InetAddress.getAllByName(hostname); ArrayList endPoints = new ArrayList(); for (Iterator i = objs.iterator(); i.hasNext();) { ObjectName obj = i.next(); String scheme = mbs.getAttribute(obj, "scheme").toString(); String port = obj.getKeyProperty("port"); for (InetAddress addr : addresses) { if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || addr.isMulticastAddress()) { continue; } String host = addr.getHostAddress(); String ep = scheme + "://" + host + ":" + port; endPoints.add(ep); } } return endPoints; } 

你会得到一个像这样的列表:

 [http://192.168.1.22:8080] 

对于任何对我们如何解决这个问题感兴趣的人,这里是模拟代码

 Server server = ServerFactory.getServer(); Service[] services = server.findServices(); for (Service service : services) { for (Connector connector : service.findConnectors()) { ProtocolHandler protocolHandler = connector.getProtocolHandler(); if (protocolHandler instanceof Http11Protocol || protocolHandler instanceof Http11AprProtocol || protocolHandler instanceof Http11NioProtocol) { serverPort = connector.getPort(); System.out.println("HTTP Port: " + connector.getPort()); } } } 
 public void getIpAddressAndPort() throws MalformedObjectNameException, NullPointerException, UnknownHostException { MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); Set objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"))); String host = InetAddress.getLocalHost().getHostAddress(); String port = objectNames.iterator().next().getKeyProperty("port"); System.out.println("IP Address of System : "+host ); System.out.println("port of tomcat server : "+port); } 

服务器端口号不存在。 它可以有任意数量的端口号。 所以你问的是没有意义的。 与特定请求关联端口号确实有意义。

  • 获取Tomcat / Server实例的MBean / JMX对象
  • 从那里获取虚拟服务器实例相关数据

查看http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/java/com/sun/enterprise/web/WebContainer.java以供参考

然后可以通过协议连接器[RMI / IIOP]或协议适配器[SNMP / HTTP]实现的各种协议公开MBeanServer的内容。 在这种情况下,使用SNMP适配器将是一种更好的方法,因此可以在不知道其他应用服务器的确切IP /端口的情况下放置SNMP陷阱

这些类型的服务器旨在能够监听(几乎)任意端口,并从通常不需要知道的所包含的应用程序中隐藏这些细节。

唯一的方法是自己读取配置文件, 并且可以访问启动服务器的命令行参数,这些参数可能已被覆盖配置文件。 您必须了解正在运行的系统才能使用此function。 没有办法可以轻松地做到这一点。

即使有,也有一些情况,它就像在NAT后面,某些防火墙等无关紧要。

您可以使用crossContext 。 但我不认为这是app服务器不可知的。

我将共享一个自定义类,表现为通过JNDI在同一个tomcat实例中运行应用程序的注册表,正如我在这里解释的那样。

在启动期间,通过ContextListener或通过Spring容器事件,我将通过JNDI查找获取注册表,使用从servletcontext.contextpath获取的URL添加我的Web应用程序实例,最后注册一个侦听器以听取其他应用程序注册自己。 这是我能想到的更多服务器不可知论者。

获取端口不会与服务器无关,您应该使用context参数。

编辑:对不起,忘了说我所描述的是在上下文之间共享对象,但不,你不能不知道端口,除非你使用一些服务器API(根本不是不可知)。

我不完全确定您是否可以从您需要的环境配置中的代码访问Tomcat端口。 您是否考虑过将Web服务的完整URL作为配置参数/设置(可能在.properties文件中)传递给应用程序?

这样您就不必对端口进行硬编码并将两个应用程序分离,以便技术上可以在外部tomcat上使用Web服务,但仍然只需更改属性即可访问它,从而避免重新构建代码。

以前在大型分布式项目中,我使用的设计是让集中式服务使用中央服务的URL(和端口)初始化多个服务。

显然,这意味着中央服务必须维护一个要初始化的服务列表(URL和端口)。

如果要访问同一服务器实例上的应用程序,只需省略URL的服务器部分。 一些例子,你可以实现。 当前文档位于http://example.com:8080/app2/doc.html

  • xxx.html变为http://example.com:8080/app2/xxx.html
  • ../xxx.html成为http://example.com:8080/xxx.html
  • ../xxx.html成为http://example.com:8080/xxx.html
  • ../foo/xxx.html成为http://example.com:8080/foo/xxx.html
  • ../../xxx.html成为http://example.com:8080/xxx.html (没有办法超越根)
  • /xxx.html成为http://example.com:8080/xxx.html 这可能就是你要找的东西。
  • //other.com/xxx.html成为http://example.com:8080/xxx.html如果您想保留“https:”,则非常有用

嗯,没有请求,应用程序如何在Tomcat中启动? 也许我现在脑子里已经死了一会儿,但我不认为任何课程会在请求到来之前加载。 当然,你可以拥有独立于任何特定请求的类,但是他们需要一个请求来让它们在某些时候被解雇。