This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 1405a9d  [ISSUE #2860] spring cloud client auto set port (#2861)
1405a9d is described below

commit 1405a9d5f500a7bf358e62935a108f5105d063cb
Author: dragon-zhang <[email protected]>
AuthorDate: Fri Feb 11 19:52:11 2022 +0800

    [ISSUE #2860] spring cloud client auto set port (#2861)
    
    * spring cloud client auto set port
    
    * add note
    
    * fix code style
    
    * compatible with springboot 1.x
---
 .../springcloud/init/ContextRegisterListener.java  | 80 +++++++++++++++++-----
 .../src/main/resources/application.yml             |  2 +-
 2 files changed, 63 insertions(+), 19 deletions(-)

diff --git 
a/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/init/ContextRegisterListener.java
 
b/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/init/ContextRegisterListener.java
index 9958d47..ebd993c 100644
--- 
a/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/init/ContextRegisterListener.java
+++ 
b/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/init/ContextRegisterListener.java
@@ -22,41 +22,50 @@ import 
org.apache.shenyu.client.core.constant.ShenyuClientConstants;
 import 
org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher;
 import 
org.apache.shenyu.client.core.exception.ShenyuClientIllegalArgumentException;
 import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.common.exception.ShenyuException;
 import org.apache.shenyu.common.utils.IpUtils;
 import org.apache.shenyu.register.common.config.PropertiesConfig;
 import org.apache.shenyu.register.common.dto.MetaDataRegisterDTO;
 import org.apache.shenyu.register.common.dto.URIRegisterDTO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.core.env.Environment;
 import org.springframework.lang.NonNull;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * The type Context register listener.
  */
-public class ContextRegisterListener implements 
ApplicationListener<ContextRefreshedEvent> {
-    
+public class ContextRegisterListener implements 
ApplicationListener<ContextRefreshedEvent>, BeanFactoryAware {
+
     private static final Logger LOG = 
LoggerFactory.getLogger(ContextRegisterListener.class);
-    
+
     private final ShenyuClientRegisterEventPublisher publisher = 
ShenyuClientRegisterEventPublisher.getInstance();
-    
+
     private final AtomicBoolean registered = new AtomicBoolean(false);
-    
+
     private final Boolean isFull;
-    
+
     private final String host;
-    
+
     private final String contextPath;
-    
+
     private final String appName;
-    
+
     private final Integer port;
-    
+
+    private BeanFactory beanFactory;
+
     /**
      * Instantiates a new Context register listener.
      *
@@ -74,23 +83,59 @@ public class ContextRegisterListener implements 
ApplicationListener<ContextRefre
                 throw new ShenyuClientIllegalArgumentException(errorMsg);
             }
         }
-        port = Integer.parseInt(props.getProperty(ShenyuClientConstants.PORT));
+        this.port = 
Integer.parseInt(Optional.ofNullable(props.getProperty(ShenyuClientConstants.PORT)).orElseGet(()
 -> "-1"));
         this.appName = env.getProperty("spring.application.name");
         this.host = props.getProperty(ShenyuClientConstants.HOST);
     }
-    
+
     @Override
-    public void onApplicationEvent(@NonNull final ContextRefreshedEvent 
contextRefreshedEvent) {
+    public void setBeanFactory(final BeanFactory beanFactory) throws 
BeansException {
+        this.beanFactory = beanFactory;
+    }
+
+    @Override
+    public void onApplicationEvent(@NonNull final ContextRefreshedEvent 
webServerInitializedEvent) {
         if (!registered.compareAndSet(false, true)) {
             return;
         }
         if (Boolean.TRUE.equals(isFull)) {
             publisher.publishEvent(buildMetaDataDTO());
         }
-        publisher.publishEvent(buildUriRegisterDTO());
+        final int mergedPort = port <= 0 ? findPort() : port;
+        publisher.publishEvent(buildUriRegisterDTO(mergedPort));
+    }
+
+    /**
+     * Note: springboot 1.x version has been made compatible.
+     * Note: In this way, no matter what container is actually used,
+     * you can get the port that is actually started in the end.
+     *
+     * @see 
org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer#getPort()
+     * @see 
org.springframework.boot.web.server.AbstractConfigurableWebServerFactory#getPort()
+     */
+    @SuppressWarnings("all")
+    private int findPort() {
+        try {
+            //works fine for springboot 2.x
+            return 
getPort("org.springframework.boot.web.server.AbstractConfigurableWebServerFactory");
+        } catch (Exception e) {
+            try {
+                //works fine for springboot 1.x
+                return 
getPort("org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer");
+            } catch (Exception exception) {
+                throw new ShenyuException("can not find port automatically ! 
try to config ${shenyu.client.springCloud.props.port}");
+            }
+        }
+    }
+
+    private int getPort(final String className) throws ClassNotFoundException, 
NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        final Class<?> clazz = Class.forName(className);
+        final Method method = clazz.getMethod("getPort");
+        final Object bean = beanFactory.getBean(clazz);
+        return (int) method.invoke(bean);
     }
-    
-    private URIRegisterDTO buildUriRegisterDTO() {
+
+    private URIRegisterDTO buildUriRegisterDTO(final int port) {
         return URIRegisterDTO.builder()
                 .contextPath(this.contextPath)
                 .appName(appName)
@@ -98,9 +143,8 @@ public class ContextRegisterListener implements 
ApplicationListener<ContextRefre
                 .port(port)
                 .rpcType(RpcTypeEnum.SPRING_CLOUD.getName())
                 .build();
-        
     }
-    
+
     private MetaDataRegisterDTO buildMetaDataDTO() {
         return MetaDataRegisterDTO.builder()
                 .contextPath(contextPath)
diff --git 
a/shenyu-examples/shenyu-examples-springcloud/src/main/resources/application.yml
 
b/shenyu-examples/shenyu-examples-springcloud/src/main/resources/application.yml
index 46e6892..7ed8571 100644
--- 
a/shenyu-examples/shenyu-examples-springcloud/src/main/resources/application.yml
+++ 
b/shenyu-examples/shenyu-examples-springcloud/src/main/resources/application.yml
@@ -47,7 +47,7 @@ shenyu:
     springCloud:
       props:
         contextPath: /springcloud
-        port: 8884
+#        port: 8884
 
 logging:
   level:

Reply via email to