简体   繁体   English

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

[英]In Java 8, how do I get my hostname without hard-coding it in my environment?

We just upgraded to Java 8 on Amazon Linux. 我们刚刚在Amazon Linux上升级到Java 8。 We are using Spring 4.3.8.RELEASE. 我们正在使用Spring 4.3.8.RELEASE。 It used to be that we could get our machine hostname by setting up beans in our application context file like so ... 过去我们可以通过在应用程序上下文文件中设置bean来获取我们的机器主机名,就像这样...

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

But with Java 8, the bean "hostname" now contains the string 但是对于Java 8,bean“hostname”现在包含字符串

localhost

Before Java 8, it used to contain the "hostname" value as run on the command line, which is 在Java 8之前,它曾用于包含在命令行上运行的“hostname”值,即

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

How can I reconfigure our bean so that it gets the hostname that the command line lists out? 如何重新配置​​我们的bean以便它获取命令行列出的主机名? I don't want to hard-code anything anywhere. 我不想在任何地方硬编码。

From InetAddress java 8 is not getting the hostname : InetAddress java 8获取主机名

There was similar bug fired in JDK. 在JDK中发生了类似的错误。

What I understand is that they changed default resolution process. 据我所知,他们改变了默认解析过程。

They honor configuration in /etc/nsswitch.conf where hosts are configured for /etc/hosts that gives it main priority for name resolution. 他们尊重/etc/nsswitch.conf中的配置,其中为/ etc / hosts配置了主机,为其提供了名称解析的主要优先级。

Usually /etc/hosts has record for 127.0.0.1 localhost that provide name for host localhost 通常/ etc / hosts具有为主机localhost提供名称的127.0.0.1 localhost的记录

You could try InetAddress.getCanonicalHostName() 你可以尝试InetAddress.getCanonicalHostName()

The JavaDocs for getCanonicalHostName() says getCanonicalHostName()的JavaDocs说

Gets the fully qualified domain name for this IP address. 获取此IP地址的完全限定域名。 Best effort method, meaning we may not be able to return the FQDN depending on the underlying system configuration. 尽力而为方法,这意味着我们可能无法返回FQDN,具体取决于底层系统配置。

You really have three options of differing complexity and information value: 您确实有三种不同复杂性和信息价值的选择:

  1. Actually run the hostname command using Runtime . 实际上使用Runtime运行hostname命令。 It's fairly portable and should work pretty much everywhere. 它相当便携,几乎可以在任何地方工作。 (Maybe not on IBM's Mainframes) (可能不在IBM的大型机上)
  2. Grab all available network interfaces and get their hostnames. 获取所有可用的网络接口并获取其主机名。 https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html https://docs.oracle.com/javase/tutorial/networking/nifs/listing.html
  3. Set an environment or system property as the value of hostname . 将环境或系统属性设置为hostname的值。
    Like java -Dmy.hostname= hostname ... java -Dmy.hostname = hostname ...

Sad part is that it's not that straightforward in Spring XML. 可悲的是,它在Spring XML中并不那么简单。

All other options are known to give varying degrees of accuracy. 众所周知,所有其他选项都具有不同程度的准确性。 Like 127.0.0.1 will likely resolve to localhost or localhost.localdomain . 127.0.0.1可能会解析为localhostlocalhost.localdomain

Alternatively, you can run the hostname linux command using Java Runtime, code should be something like below: 或者,您可以使用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();

I believe Java still calls the native gethostname() , but couldn't say why this fails. 我相信Java仍然会调用本机gethostname() ,但不能说为什么会失败。

For Linux, you could try this alternative: 对于Linux,您可以尝试这种替代方案:

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

Since my comment got lost in the stream, please try 由于我的评论在流中丢失了,请尝试

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

Have a look at Amazon's documemtation if the result does not suits your needs. 如果结果不符合您的需求,请查看亚马逊的文档

I can be better to define a property in your .properties file for hostname like. 我可以更好地在.properties文件中为hostname定义一个属性。

hostname=myserver.mydomain.com

And use it in your application. 并在您的应用程序中使用它。 This way is not harcoded. 这种方式没有被编码。 It also avoid dependency to operating system config which can be changed without attention. 它还避免了对操作系统配置的依赖,操作系统配置可以在不注意的情

InetAddress in Java 8 had a bug regarding the resolution of hostname. Java 8中的InetAddress有关于主机名解析的错误 The bug was reported in version 8u20 and has been fixed since then. 该错误在版本8u20中报告,并且从那时起已经修复。 Please check that you are not on this version. 请检查您是否使用此版本。 If not, then using InetAddress.getLocalHost().getHostName() will give you the hostname. 如果没有,那么使用InetAddress.getLocalHost().getHostName()将为您提供主机名。

Also I suggest, setting up a static hostname on the AWS instance. 我还建议在AWS实例上设置静态主机名

  1. Update /etc/hosts 更新/ etc / hosts
  2. Update /etc/hostname 更新/ etc / hostname
  3. Run hostname to check the hostname 运行hostname以检查主机名
  4. Reboot and check the persisted hostname 重新启动并检查持久化的主机名

This should allow you to read the hostname from the file if required. 这应该允许您在需要时从文件中读取主机名。

Also, if hostname command is giving the correct result, then use exec method in Runtime class to execute the command and the read the InputStream to get the response. 此外,如果hostname命令给出正确的结果,则在Runtime类中使用exec方法执行命令并读取InputStream以获取响应。

PS: You can use InetAddress.getLocalHost().isLoopbackAddress() to check whether the address is a LoopbackAddress and then use a fallback method. PS:您可以使用InetAddress.getLocalHost().isLoopbackAddress()来检查地址是否为LoopbackAddress,然后使用回退方法。

There are a similar question in the OpenJDK bugs OpenJDK中有一个类似的问题

The newer calls respect the localhosts /etc/nsswitch.conf configuration files. 较新的调用遵循localhosts /etc/nsswitch.conf配置文件。 In the case of this machine that file tells these calls to look in files before referencing other naming services. 在这台机器的情况下,该文件告诉这些调用在引用其他命名服务之前查看文件。

Since the /etc/hosts file contains an explicit mapping for this hostname / IP combination, that is what is returned. 由于/ etc / hosts文件包含此主机名/ IP组合的显式映射,因此返回的内容。

In the older JDK's the gethostbyname actually ignored the local machines settings and immediately delegated to the naming service. 在较旧的JDK中,gethostbyname实际上忽略了本地计算机设置并立即委托给命名服务。

You can always use the Runtime class for that : 您始终可以使用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);
}

But it's not so recommended as you can see 但它不是那么建议你可以看到

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在不对HTML图像进行硬编码的情况下实现Java Servlet图像的幻灯片显示? - How do I implement a slideshow of images from java servlets without hard-coding the images in my html? 如何在不对URL进行硬编码的情况下调用REST API get方法? - How can I call my REST API get method without hard-coding a URL? 我可以在没有硬编码的情况下在 Windows 上运行 Java 中构建 Linux 路径吗? - Can I build a Linux path in Java running on Windows without hard-coding? 如何在不对目录进行硬编码的情况下将某些内容保存到桌面? - How to save something to the desktop without hard-coding the directory? 用Java硬编码Map的替代方法? - Alternative ways for hard-coding Map in Java? 从工厂请求项目,而无需对每种情况进行硬编码 - Requesting item from Factory without hard-coding every case 如果被告知使用系统属性line.separator而不是硬编码\\ n,为什么我的代码在Windows上可以工作? - If we're told to use the system property line.separator instead of hard-coding \n, why does my code work on Windows? 避免硬编码休眠属性 - Avoid hard-coding Hibernate properties 从 android 应用程序访问 AWS S3,无需硬编码访问密钥 - Accessing AWS S3 from android app without hard-coding access keys How to write test result(pass/fail) in excel sheet using selenium web driver and java without hard coding row_num and Col_num in my program - How to write test result(pass/fail) in excel sheet using selenium web driver and java without hard coding row_num and Col_num in my program
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM