【发布时间】:2016-12-19 08:44:54
【问题描述】:
如何在运行时获取部署应用程序的主机和端口,以便在我的 java 方法中使用它?
【问题讨论】:
-
spring boot 应用的端口怎么定义?
标签: spring-boot port host
如何在运行时获取部署应用程序的主机和端口,以便在我的 java 方法中使用它?
【问题讨论】:
标签: spring-boot port host
您可以通过Environment 获取此信息,对于port 和host 您可以使用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();
}
【讨论】:
ApplicationListener<EmbeddedServletContainerInitializedEvent>,并从提供的事件中获取端口。
local.server.port而不是server.port会是更好的选择(server.port=0)。
如果你使用像server.port=${random.int[10000,20000]}这样的随机端口方法。并在 Java 代码中读取Environment 中的端口,使用@Value 或getProperty("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;
}
【讨论】:
这是一个 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;
}
【讨论】:
对于主机: 正如安东所提到的
// 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
【讨论】:
上面的答案只是一个完整的例子
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();
}
}
}
【讨论】:
在运行时绑定的端口可以被注入为:
@Value('${local.server.port}')
private int port;
【讨论】: