在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,具体取决于底层系统配置。

您确实有三种不同的复杂性和信息价值选择:

  1. 实际上使用Runtime运行hostname命令。 它相当便携,几乎可以在任何地方使用。 (可能不在IBM的大型机上)
  2. 获取所有可用的网络接口并获取其主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  3. 将环境或系统属性设置为hostname的值。
    java -Dmy.hostname = hostname

可悲的是,它在Spring XML中并不那么简单。

众所周知,所有其他选项都具有不同程度的准确性。 像127.0.0.1可能会解析为localhostlocalhost.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实例上设置静态主机名 。

  1. 更新/ etc / hosts
  2. 更新/ etc / hostname
  3. 运行hostname以检查主机名
  4. 重新启动并检查持久化的主机名

这应该允许您在需要时从文件中读取主机名。

此外,如果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);