如何在运行时获取 SPRING Boot HOST 和 PORT 地址?

Posted

技术标签:

【中文标题】如何在运行时获取 SPRING Boot HOST 和 PORT 地址?【英文标题】:How to get the SPRING Boot HOST and PORT address during run time? 【发布时间】:2016-12-19 08:44:54 【问题描述】:

如何在运行时获取部署应用程序的主机和端口,以便在我的 java 方法中使用它?

【问题讨论】:

spring boot 应用的端口怎么定义? 这能回答你的问题吗? How to get local server host and port in Spring Boot? 【参考方案1】:

您可以通过Environment 获取此信息,对于porthost 您可以使用InternetAddress 获取。

@Autowired
Environment environment;

// Port via annotation
@Value("$server.port")
int aPort;

......
public void somePlaceInTheCode() 
    // Port
    environment.getProperty("server.port");
    
    // Local address
    InetAddress.getLocalHost().getHostAddress();
    InetAddress.getLocalHost().getHostName();
    
    // Remote address
    InetAddress.getLoopbackAddress().getHostAddress();
    InetAddress.getLoopbackAddress().getHostName();

【讨论】:

只有在以下情况下才能以这种方式获取端口:a) 端口实际上是显式配置的,并且 b) 它没有设置为 0(意味着 servlet 容器将在启动时选择一个随机端口)。要获取实际端口,需要实现ApplicationListener<EmbeddedServletContainerInitializedEvent>,并从提供的事件中获取端口。 在使用随机端口的情况下,使用local.server.port而不是server.port会是更好的选择(server.port=0)。 环回地址(127.0.0.1)是远程地址吗? “本地地址”和“远程地址”地址有什么区别?【参考方案2】:

如果你使用像server.port=$random.int[10000,20000]这样的随机端口方法。并在 Java 代码中读取Environment 中的端口,使用@ValuegetProperty("server.port")你会得到一个不可预测的端口,因为它是随机的。

ApplicationListener,你可以重写 onApplicationEvent 来获取设置后的端口号。

在 Spring boot 版本中实现 Spring 接口 ApplicationListener<EmbeddedServletContainerInitializedEvent>(Spring boot 版本 1) 或 ApplicationListener<WebServerInitializedEvent>(Spring boot 版本 2) 覆盖 onApplicationEvent 以获取 Fact Port。

弹簧靴1

@Override
public void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) 
    int port = event.getEmbeddedServletContainer().getPort();

弹簧靴2

@Override
public void onApplicationEvent(WebServerInitializedEvent event) 
    Integer port = event.getWebServer().getPort();
    this.port = port;

【讨论】:

【参考方案3】:

这是一个 util 组件:

EnvUtil.java(放入适当的包中,成为一个组件。)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Environment util.
 */
@Component
public class EnvUtil 
    @Autowired
    Environment environment;

    private String port;
    private String hostname;

    /**
     * Get port.
     *
     * @return
     */
    public String getPort() 
        if (port == null) port = environment.getProperty("local.server.port");
        return port;
    

    /**
     * Get port, as Integer.
     *
     * @return
     */
    public Integer getPortAsInt() 
        return Integer.valueOf(getPort());
    

    /**
     * Get hostname.
     *
     * @return
     */
    public String getHostname() throws UnknownHostException 
        // TODO ... would this cache cause issue, when network env change ???
        if (hostname == null) hostname = InetAddress.getLocalHost().getHostAddress();
        return hostname;
    

    public String getServerUrlPrefi() throws UnknownHostException 
        return "http://" + getHostname() + ":" + getPort();
    

示例 - 使用 util:

然后可以注入 util,并调用它的方法。 这是控制器中的一个示例:

// inject it,
@Autowired
private EnvUtil envUtil;

/**
 * env
 *
 * @return
 */
@GetMapping(path = "/env")
@ResponseBody
public Object env() throws UnknownHostException 
    Map<String, Object> map = new HashMap<>();
    map.put("port", envUtil.getPort());
    map.put("host", envUtil.getHostname());
    return map;

【讨论】:

【参考方案4】:

对于主机: 正如安东所提到的

// Local address
InetAddress.getLocalHost().getHostAddress();
InetAddress.getLocalHost().getHostName();

// Remote address
InetAddress.getLoopbackAddress().getHostAddress();
InetAddress.getLoopbackAddress().getHostName();

端口: 正如 Nicolai 所提到的,只有在显式配置且未设置为 0 的情况下,您才能通过 environment 属性检索此信息。

有关该主题的 Spring 文档: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-discover-the-http-port-at-runtime

对于执行此操作的实际方法,此处已回答: Spring Boot - How to get the running port

这里有一个关于如何实现它的 github 示例: https://github.com/hosuaby/example-restful-project/blob/master/src/main/java/io/hosuaby/restful/PortHolder.java

【讨论】:

【参考方案5】:

上面的答案只是一个完整的例子

package bj;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;

import java.net.InetAddress;
import java.net.UnknownHostException;

@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
@SpringBootApplication
class App implements ApplicationListener<ApplicationReadyEvent> 

    @Autowired
    private ApplicationContext applicationContext;

    public static void main(String[] args) 
        SpringApplication.run(App.class, args);
    

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) 
        try 
            String ip = InetAddress.getLocalHost().getHostAddress();
            int port = applicationContext.getBean(Environment.class).getProperty("server.port", Integer.class, 8080);
            System.out.printf("%s:%d", ip, port);
         catch (UnknownHostException e) 
            e.printStackTrace();
        
    

【讨论】:

【参考方案6】:

在运行时绑定的端口可以被注入为:

@Value('$local.server.port')
private int port;

【讨论】:

以上是关于如何在运行时获取 SPRING Boot HOST 和 PORT 地址?的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot - 如何获取正在运行的端口和IP地址[重复]

如何在 Spring Boot 测试中获取正在运行的服务器端口?

在运行 Spring MVC 应用程序时在 Spring Boot 中获取 NoSuchMethodError: javax.servlet.ServletContext.addServlet

在 Pod 上运行时采用 Spring Boot Heapdump 和 Thread Dumps

如何在 Spring Boot 2 oauth2 中获取令牌?

如何获取spring boot application.yml里面的值