【发布时间】:2010-11-04 02:27:14
【问题描述】:
如果java客户端调用不同服务器上的远程EJB,如何获取客户端IP地址?请注意,从服务器获取它很重要,因为客户端可能位于 NAT 防火墙后面,在这种情况下,我们需要公共 IP 地址。
注意:虽然它最好是一个通用的解决方案,但至少我可以使用一个从 JBoss 4.2.2 上的 EJB2 调用中检索 IP 地址的解决方案
【问题讨论】:
标签: java ip-address ejb
如果java客户端调用不同服务器上的远程EJB,如何获取客户端IP地址?请注意,从服务器获取它很重要,因为客户端可能位于 NAT 防火墙后面,在这种情况下,我们需要公共 IP 地址。
注意:虽然它最好是一个通用的解决方案,但至少我可以使用一个从 JBoss 4.2.2 上的 EJB2 调用中检索 IP 地址的解决方案
【问题讨论】:
标签: java ip-address ejb
我相信当前工作线程的名称包含服务器的 IP 地址,但不包含客户端的 IP,因为线程是池化的,而不是为每次调用创建的。在 JBoss 4 中,可以使用以下解决方法来获取客户端的 IP 地址:
try {
//Reflection is used to avoid compile-time dependency on JBoss internal libraries
Class clazz = Class.forName("org.jboss.web.tomcat.security.HttpServletRequestPolicyContextHandler");
Field requestContextField = clazz.getDeclaredField("requestContext");
requestContextField.setAccessible(true);
ThreadLocal ctx = (ThreadLocal) requestContextField.get(null);
ServletRequest req = ((ServletRequest) ctx.get());
return req==null?null:req.getRemoteAddr();
} catch (Exception e) {
LOG.log(Level.WARNING, "Failed to determine client IP address",e);
}
【讨论】:
感谢 MicSim,我了解到线程名称存储了 IP 地址。在 JBoss 4.2.2 中,EJB2 项的线程名称如下所示:
http-127.0.0.1-8080-2
(我假设 http 是可选的,取决于实际使用的协议)。
这可以用正则表达式解析:
Pattern pattern = Pattern.compile("\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b");
Matcher matcher = pattern.matcher(Thread.currentThread().getName());
if (matcher.find()) {
return matcher.group();
}
return "";
【讨论】:
JBoss 社区 wiki 上的This article 正好解决了您的问题。在 JBoss 5 之前,IP 地址显然必须从工作线程名称中解析出来。这似乎是在早期版本上执行此操作的唯一方法。这是代码 sn-p 做它(从上面的链接复制):
private String getCurrentClientIpAddress() {
String currentThreadName = Thread.currentThread().getName();
System.out.println("Threadname: "+currentThreadName);
int begin = currentThreadName.indexOf('[') +1;
int end = currentThreadName.indexOf(']')-1;
String remoteClient = currentThreadName.substring(begin, end);
return remoteClient;
}
【讨论】:
你试过:java.rmi.server.RemoteServer.getClientHost() 吗?
http://java.sun.com/j2se/1.5.0/docs/api/java/rmi/server/RemoteServer.html#getClientHost()
【讨论】: