获取服务器程序监听的端口号,网上的方法都试过,都不管用。联想到eureka 客户端注册的时候需要获取到自己的实例信息,提交到eureka服务器上,eureka client里面肯定有获取端口号的方法。
找源码过程略。
package spring-cloud-netflix-eureka-client/2.0.0.RELEASE/spring-cloud-netflix-eureka-client-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/eureka/serviceregistry/EurekaAutoServiceRegistration.java
这个包是spring提供的,而不是netflix的eureka-client
// line 119
@EventListener(WebServerInitializedEvent.class)
public void onApplicationEvent(WebServerInitializedEvent event) {
// TODO: take SSL into account
int localPort = event.getWebServer().getPort();
if (this.port.get() == 0) {
log.info("Updating port to " + localPort);
this.port.compareAndSet(0, localPort);
start(); // start函数开始注册过程,就是在WebServer完全启动之后才开始执行客户端的注册。
}
}
这个方法监听事件WebServerInitializedEvent
,然后从对象中获取到了端口号。看看这个类的文档:
Event to be published after the application context is refreshed and the WebServer is ready. Useful for obtaining the local port of a running server.
正好就是用于获取本地端口的事件。
但是这个事件的发布时间一般比创建Bean的时间晚(我测试的都是这样的)。所以使用的时候需要注意,像下面的是有问题的:
// 以下是错误示范!
@Configuration
public class ServiceConfig{
int port;
// 事件发布之后把端口号保存在成员变量中
@EventListener(WebServerInitializedEvent.class){
public void onApplicationEvent(WebServerInitializedEvent event) {
this.port = event.getWebServer().getPort();
}
// 然后创建bean的时候使用这个变量??
// 想多了,这个bean先创建的,结果是AService使用的port为0
@Bean
public AService aService(){
return new AService(this.port);
}
}
解决办法挺多的,例如
- bean提供setPort方法,事件发布的时候调用set方法。WebServerInitializedEvent有获取ApplicationContext的方法,有了applicationContext就能获取已创建好的某个bean
- port定义为引用类型
...