在Java 8中,如何在不在我的环境中对其进行硬编码的情况下获取主机名?

时间:2018-01-18 15:47:26

标签: java linux spring java-8 hostname

我们刚刚在Amazon Linux上升级到Java 8。我们正在使用Spring 4.3.8.RELEASE。过去我们可以通过在应用程序上下文文件中设置bean来获取我们的机器主机名,如此...

<bean id="localhostInetAddress" class="java.net.InetAddress" factory-method="getLocalHost" />
<bean id="hostname" factory-bean="localhostInetAddress" factory-method="getHostName" />

但是使用Java 8,bean“hostname”现在包含字符串

localhost

在Java 8之前,它曾用于包含在命令行上运行的“hostname”值,即

[myuser@machine1 ~]$ hostname
machine1.mydomain.org

如何重新配置​​我们的bean,以便它获取命令行列出的主机名?我不想在任何地方硬编码。

9 个答案:

答案 0 :(得分:4)

来自InetAddress java 8 is not getting the hostname

  

在JDK中发生了类似的错误。

     

据我所知,他们改变了默认解决方案。

     

他们尊重/etc/nsswitch.conf中的配置,其中为/ etc / hosts配置了主机,为其提供了名称解析的主要优先级。

     

通常/ etc / hosts有127.0.0.1 localhost的记录,它提供了host localhost的名称

答案 1 :(得分:2)

您可以尝试InetAddress.getCanonicalHostName()

getCanonicalHostName()的JavaDocs说

  

获取此IP地址的完全限定域名。尽力而为方法,这意味着我们可能无法返回FQDN,具体取决于底层系统配置。

答案 2 :(得分:2)

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

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

    众所周知,所有其他选项都具有不同程度的准确性。 与 127.0.0.1 一样,可能会解析为 localhost localhost.localdomain

答案 3 :(得分:2)

或者,您可以使用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();

答案 4 :(得分:2)

我相信Java仍然会调用原生gethostname(),但无法说明为什么会失败。

对于Linux,您可以尝试以下方法:

String hostname = new String(Files.readAllBytes(Paths.get("/proc/sys/kernel/hostname")), StandardCharsets.US_ASCII);

答案 5 :(得分:2)

由于我的评论在流中丢失了,请尝试

<bean id="hostname" class="com.amazonaws.util.EC2MetadataUtils" factory-method="getLocalHostName()">

如果结果不符合您的需求,请查看Amazon's documemtation

答案 6 :(得分:2)

我可以更好地在.properties文件中为hostname定义一个属性,如。

hostname=myserver.mydomain.com

并在您的应用程序中使用它。这种方式没有被编码。它还避免了对操作系统配置的依赖,操作系统配置可以在没有注意的情况下进行更改

答案 7 :(得分:2)

Java 8中的InetAddress有关于主机名解析的bug。该错误在版本8u20中报告,并且从那时起已经修复。请检查您是否使用此版本。如果没有,那么使用InetAddress.getLocalHost().getHostName()将为您提供主机名。

我还建议在AWS实例上设置static hostname

  1. 更新/ etc / hosts
  2. 更新/ etc / hostname
  3. 运行hostname以检查主机名
  4. 重新启动并检查持久主机名
  5. 如果需要,这应该允许您从文件中读取主机名。

    此外,如果hostname命令给出正确的结果,则使用exec method in Runtime class执行命令并读取InputStream以获得响应。

    PS:您可以使用InetAddress.getLocalHost().isLoopbackAddress()检查地址是否为LoopbackAddress,然后使用回退方法。

答案 8 :(得分:0)

OpenJDK bugs

中有类似的问题
  

较新的调用遵循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);
}

但它并不像你see

那样推荐