在Java 8中,如何在不在我的环境中对其进行硬编码的情况下获取主机名?
我们刚刚在Amazon Linux上升级到Java 8。 我们正在使用Spring 4.3.8.RELEASE。 过去我们可以通过在应用程序上下文文件中设置bean来获取我们的机器主机名,就像这样…
但是对于Java 8,bean“hostname”现在包含字符串
localhost
在Java 8之前,它曾用于包含在命令行上运行的“hostname”值,即
[myuser@machine1 ~]$ hostname machine1.mydomain.org
如何重新配置我们的bean,以便它获取命令行列出的主机名? 我不想在任何地方硬编码。
OpenJDK中有一个类似的问题
较新的调用遵循localhosts /etc/nsswitch.conf配置文件。 对于这台机器,该文件告诉这些调用在引用其他命名服务之前查看文件。
由于/ etc / hosts文件包含此主机名/ IP组合的显式映射,因此返回的内容。
在较旧的JDK中,gethostbyname实际上忽略了本地计算机设置并立即委托给命名服务。
您始终可以使用Runtime
类:
Process hostname = Runtime.getRuntime().exec("hostname"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(hostname.getInputStream())); String s; while ((s = stdInput.readLine()) != null) { System.out.println(s); }
但是你不能这么推荐
从InetAddress java 8获取主机名 :
在JDK中发生了类似的错误。
据我所知,他们改变了默认解析过程。
他们尊重/etc/nsswitch.conf中的配置,其中为/ etc / hosts配置了主机,为其提供了名称解析的主要优先级。
通常/ etc / hosts具有为主机localhost提供名称的127.0.0.1 localhost记录
你可以尝试InetAddress.getCanonicalHostName()
getCanonicalHostName()的JavaDocs说
获取此IP地址的完全限定域名。 尽力而为方法,这意味着我们可能无法返回FQDN,具体取决于底层系统配置。
您确实有三种不同的复杂性和信息价值选择:
- 实际上使用Runtime运行hostname命令。 它相当便携,几乎可以在任何地方使用。 (可能不在IBM的大型机上)
- 获取所有可用的网络接口并获取其主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
- 将环境或系统属性设置为hostname的值。
像java -Dmy.hostname =hostname
…
可悲的是,它在Spring XML中并不那么简单。
众所周知,所有其他选项都具有不同程度的准确性。 像127.0.0.1可能会解析为localhost或localhost.localdomain 。
或者,您可以使用Java Runtime运行hostname linux命令,代码应如下所示:
String cmdResult=""; Runtime r = Runtime.getRuntime(); Process p = r.exec("hostname"); BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) { cmdResult += inputLine; } in.close();
由于我的评论在流中丢失了,请尝试
如果结果不符合您的需求,请查看亚马逊的文档 。
我可以更好地在.properties文件中为hostname定义一个属性。
hostname=myserver.mydomain.com
并在您的应用程序中使用它。 这种方式没有被编码。 它还避免了对操作系统配置的依赖,操作系统配置可以在不注意的情
Java 8中的InetAddress有关于主机名解析的错误 。 该错误在版本8u20中报告,并且从那时起已经修复。 请检查您是否使用此版本。 如果没有,那么使用InetAddress.getLocalHost().getHostName()
将为您提供主机名。
我还建议在AWS实例上设置静态主机名 。
- 更新/ etc / hosts
- 更新/ etc / hostname
- 运行
hostname
以检查主机名 - 重新启动并检查持久化的主机名
这应该允许您在需要时从文件中读取主机名。
此外,如果hostname
命令给出正确的结果,则在Runtime类中使用exec方法执行命令并读取InputStream以获取响应。
PS:您可以使用InetAddress.getLocalHost().isLoopbackAddress()
来检查地址是否为LoopbackAddress,然后使用回退方法。
我相信Java仍然会调用本机gethostname()
,但不能说为什么会失败。
对于Linux,您可以尝试这种替代方案:
String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);