是否有任何Tomcat API或配置可以告诉应用程序(可能在启动时),它在没有请求的情况下运行的端口是什么?
想象一下这样一种场景:在同一个Tomcat中运行两个Web应用程序,其中一个需要从另一个Web服务调用Web服务。我们不希望请求离开Tomcat(如果您使用Apache服务器名称或绝对URL,请求将退出并再次返回,它可以转到任何实例)并返回。为此,我知道机器名称但无法获取端口号。我知道我可以硬编码这些信息,但我不想这样做,因为我希望我的war
文件与应用服务器无关。
我知道如果我们有HTTPServletRequest
我们就能找到它这仅适用于Tomcat 6,不适用于Tomcat 7
答案 0 :(得分:25)
有了这个:
List<String> 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<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"), query);
String hostname = InetAddress.getLocalHost().getHostName();
InetAddress[] addresses = InetAddress.getAllByName(hostname);
ArrayList<String> endPoints = new ArrayList<String>();
for (Iterator<ObjectName> 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]
答案 1 :(得分:21)
对于任何对我们如何解决这个问题感兴趣的人,这里是模拟代码
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());
}
}
}
答案 2 :(得分:4)
public void getIpAddressAndPort()
throws MalformedObjectNameException, NullPointerException,
UnknownHostException {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> 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);
}
答案 3 :(得分:2)
服务器端口号不存在。它可以有任意数量的端口号。所以你问的是没有意义的。 与特定请求相关联的端口号确实有意义。
答案 4 :(得分:1)
您可以使用crossContext。但我不认为这是app服务器不可知的。
我将共享一个自定义类,表现为通过JNDI在同一个tomcat实例中运行应用程序的注册表,正如我解释here。
在启动期间,通过ContextListener
或通过Spring容器事件,我将通过JNDI查找获取注册表,使用从servletcontext.contextpath获取的URL添加我的Web应用程序实例,最后注册一个侦听器听取其他申请注册。这是我能想到的服务器不可知论者。
获取端口不会与服务器无关,您应该使用上下文参数。
编辑:对不起,忘了说我所描述的是在上下文之间共享对象,但不,除非你使用一些服务器API(根本不是不可知),否则你不能不知道端口。答案 5 :(得分:1)
然后可以通过协议连接器[RMI / IIOP]或协议适配器[SNMP / HTTP] 实现的各种协议公开 MBeanServer的内容。在这种情况下,使用SNMP适配器将是一种更好的方法,因此可以在不知道其他应用服务器的确切IP /端口的情况下放置 SNMP陷阱
答案 6 :(得分:1)
这些类型的服务器旨在能够侦听(几乎)任意端口,并从通常不需要知道的所包含的应用程序中隐藏这些细节。
唯一的方法是自己读取配置文件和可以访问启动服务器的命令行参数,这些参数可能已被覆盖配置文件。您必须了解正在运行的系统才能使其正常工作。没有办法便携。
即使有,也有一些情况,如在NAT,某些防火墙等背后无关紧要
答案 7 :(得分:0)
我不完全确定您是否可以从您需要的环境配置中的代码访问Tomcat端口。您是否考虑过将Web服务的完整URL作为配置参数/设置(可能在.properties文件中)传递给应用程序?
通过这种方式,您不必对端口进行硬编码并将两个应用程序分离,这样您就可以在外部tomcat上实现Web服务,但只需更改属性即可访问它,从而避免重新构建代码。
答案 8 :(得分:0)
以前在大型分布式项目中,我使用的设计是让集中式服务使用中央服务的URL(&amp; port)初始化多个服务。
显然,这意味着中央服务必须维护一个要初始化的服务列表(URL和端口)。
答案 9 :(得分:0)
如果要访问同一服务器实例上的应用程序,只需省略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
这可能是您所寻找的。 strong> //other.com/xxx.html
变为http://example.com:8080/xxx.html
如果您想保留“https:”答案 10 :(得分:0)
public String getPort() {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames;
try {
objectNames = beanServer.queryNames(new ObjectName("*:type=ProtocolHandler,*"),
Query.match(Query.attr("name"), Query.value("\"http-*")));
} catch (MalformedObjectNameException e) {
LOGGER.error("Port not defined!", e);
}
return objectNames.iterator().next().getKeyProperty("port");
}
public String getSecurePort() {
MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> objectNames;
try {
objectNames = beanServer.queryNames(new ObjectName("*:type=ProtocolHandler,*"),
Query.match(Query.attr("name"), Query.value("\"https-*")));
} catch (MalformedObjectNameException e) {
LOGGER.error("SecuredPort not defined!", e);
}
return objectNames.iterator().next().getKeyProperty("port");
}
答案 11 :(得分:-1)
嗯,没有请求,应用程序如何在Tomcat中启动?也许我现在脑子里已经死了一会儿,但我不认为任何课程会在请求到来之前加载。当然,你可以拥有独立于任何特定请求的类,但他们需要一个请求才能让它们在某些时候被解雇。