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

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


The following commit(s) were added to refs/heads/master by this push:
     new 9e854dc41 [type Refactor]client register base(Combination is better 
than inheritance) (#4809)
9e854dc41 is described below

commit 9e854dc413a8a410edae384f70ff8c410b9c6621
Author: likeguo <[email protected]>
AuthorDate: Thu Jul 6 22:57:40 2023 +0800

    [type Refactor]client register base(Combination is better than inheritance) 
(#4809)
    
    * feature/register
    
    * feature/register
    
    * feature/register
    
    ---------
    
    Co-authored-by: xiaoyu <[email protected]>
    Co-authored-by: tiandy tian <[email protected]>
---
 .../shenyu/client/core/register/ApiBean.java       |  84 +++++++++
 .../core/register/matcher/ApiDocProcessorImpl.java |  49 +++++
 .../client/core/register/matcher/ApiProcessor.java |  43 +++++
 .../matcher/BaseAnnotationApiProcessor.java        |  82 +++++++++
 .../registrar/ApiDocRegistrarImplImpl.java         | 203 +++++++++++++++++++++
 .../register/registrar/BaseApiRegistrarImpl.java   | 103 +++++++++++
 .../registrar/MateDataApiRegistrarImplImpl.java    | 168 +++++++++++++++++
 .../registrar/UriApiRegistrarImplImpl.java         |  76 ++++++++
 .../shenyu/client/core/utils/ApiBeanUtil.java      |  73 ++++++++
 .../register/SpringCloudApiBeansExtractor.java     |   8 +
 .../ShenyuSpringMvcClientProcessorImpl.java        |  68 +++++++
 11 files changed, 957 insertions(+)

diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/ApiBean.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/ApiBean.java
index 516686a9e..0be388702 100644
--- 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/ApiBean.java
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/ApiBean.java
@@ -73,6 +73,11 @@ public class ApiBean {
      */
     private final Properties beanProperties = new Properties();
     
+    /**
+     * status.
+     */
+    private Status status = Status.INIT;
+    
     public ApiBean(@NonNull final String clientName, @NonNull final String 
beanName, @NonNull final Object beanInstance, @NonNull final 
List<ApiDefinition> apiDefinitions) {
         this.clientName = clientName;
         this.beanName = beanName;
@@ -188,6 +193,24 @@ public class ApiBean {
         return beanProperties.getProperty(name);
     }
     
+    /**
+     * get status.
+     *
+     * @return status
+     */
+    public Status getStatus() {
+        return status;
+    }
+    
+    /**
+     * set status.
+     *
+     * @param status status
+     */
+    public void setStatus(final Status status) {
+        this.status = status;
+    }
+    
     /**
      * Gets annotation from Bean Class.
      *
@@ -259,6 +282,11 @@ public class ApiBean {
          */
         private final Properties apiProperties = new Properties();
         
+        /**
+         * status.
+         */
+        private Status status;
+        
         public ApiDefinition(final Method apiMethod) {
             this.apiMethod = apiMethod;
             this.methodPath = apiMethod.getName();
@@ -358,6 +386,23 @@ public class ApiBean {
             return apiBean;
         }
         
+        /**
+         * get status.
+         *
+         * @return staus
+         */
+        public Status getStatus() {
+            return status;
+        }
+        
+        /**
+         * set status.
+         *
+         * @param status status
+         */
+        public void setStatus(final Status status) {
+            this.status = status;
+        }
         
         /**
          * Get the annotation from Method.
@@ -383,4 +428,43 @@ public class ApiBean {
                     .orElse(null);
         }
     }
+    
+    public enum Status {
+        
+        /**
+         * init status.
+         */
+        INIT,
+        
+        /**
+         * Cannot be registered.
+         */
+        CAN_NO_BE_REGISTERED,
+        
+        /**
+         * Registrable.
+         */
+        REGISTRABLE,
+        
+        /**
+         * Registrable(only api).
+         * <br>
+         * Only register APIs included in the bean.
+         */
+        REGISTRABLE_API,
+        
+        /**
+         * Registrable(only bean).
+         * <br>
+         * A registrable bean means that the bean needs to be registered, 
ignoring the APIs in it.
+         */
+        REGISTRABLE_BEAN,
+        
+        /**
+         * Already registered.
+         * <br>
+         * Status that has already been registered should be skipped
+         */
+        REGISTERED
+    }
 }
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/ApiDocProcessorImpl.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/ApiDocProcessorImpl.java
new file mode 100644
index 000000000..ef03fff92
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/ApiDocProcessorImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.matcher;
+
+import org.apache.shenyu.client.apidocs.annotations.ApiDoc;
+import org.apache.shenyu.client.core.register.ApiBean;
+
+/**
+ * ApiDocProcessorImpl.<br>
+ * About support for {@link ApiDoc} annotations
+ *
+ * @see ApiDoc
+ */
+public class ApiDocProcessorImpl extends BaseAnnotationApiProcessor<ApiDoc> {
+    
+    @Override
+    protected void process(final ApiBean apiBean, final ApiDoc annotation) {
+        apiBean.addProperties("desc", annotation.desc());
+        apiBean.addProperties("tags", String.join(",", annotation.tags()));
+        apiBean.setStatus(ApiBean.Status.REGISTRABLE_API);
+    }
+    
+    @Override
+    protected void process(final ApiBean.ApiDefinition definition, final 
ApiDoc annotation) {
+        definition.addProperties("desc", annotation.desc());
+        definition.addProperties("tags", String.join(",", annotation.tags()));
+        definition.setStatus(ApiBean.Status.REGISTRABLE);
+    }
+    
+    @Override
+    protected Class<ApiDoc> matchAnnotation() {
+        return ApiDoc.class;
+    }
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/ApiProcessor.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/ApiProcessor.java
new file mode 100644
index 000000000..f85b84226
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/ApiProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.matcher;
+
+import org.apache.shenyu.client.core.register.ApiBean;
+
+/**
+ * ApiProcessor.<br>
+ * API bean processor.
+ */
+public interface ApiProcessor extends Matcher<ApiBean> {
+    
+    /**
+     * process.
+     *
+     * @param apiBean apiBean
+     */
+    void process(ApiBean apiBean);
+    
+    /**
+     * Determines the order in which processors are executed.
+     *
+     * @return order
+     */
+    default int order() {
+        return Integer.MAX_VALUE;
+    }
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/BaseAnnotationApiProcessor.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/BaseAnnotationApiProcessor.java
new file mode 100644
index 000000000..c8be36037
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/matcher/BaseAnnotationApiProcessor.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.matcher;
+
+import org.apache.shenyu.client.core.register.ApiBean;
+
+import java.lang.annotation.Annotation;
+import java.util.Objects;
+
+/**
+ * BaseAnnotationApiProcessor.<br>
+ * API processor that supports annotations.
+ */
+public abstract class BaseAnnotationApiProcessor<T extends Annotation> 
implements ApiProcessor {
+    
+    @Override
+    public void process(final ApiBean apiBean) {
+        final T annotation = apiBean.getAnnotation(matchAnnotation());
+        if (match(apiBean) && Objects.nonNull(annotation)) {
+            process(apiBean, annotation);
+        }
+        for (ApiBean.ApiDefinition definition : apiBean.getApiDefinitions()) {
+            final T definitionAnnotation = 
definition.getAnnotation(matchAnnotation());
+            if (match(definition) && Objects.nonNull(definitionAnnotation)) {
+                process(definition, definitionAnnotation);
+            }
+        }
+    }
+    
+    /**
+     * process API Bean.
+     *
+     * @param apiBean    apiBean
+     * @param annotation annotation
+     */
+    protected abstract void process(ApiBean apiBean, T annotation);
+    
+    /**
+     * process API.
+     *
+     * @param definition definition
+     * @param annotation annotation
+     */
+    protected abstract void process(ApiBean.ApiDefinition definition, T 
annotation);
+    
+    /**
+     * support annotation.
+     *
+     * @return annotation
+     */
+    protected abstract Class<T> matchAnnotation();
+    
+    @Override
+    public boolean match(final ApiBean element) {
+        return false;
+    }
+    
+    /**
+     * match.
+     *
+     * @param definition definition
+     * @return true
+     */
+    public boolean match(final ApiBean.ApiDefinition definition) {
+        return false;
+    }
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/ApiDocRegistrarImplImpl.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/ApiDocRegistrarImplImpl.java
new file mode 100644
index 000000000..a0dd810e7
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/ApiDocRegistrarImplImpl.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.registrar;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.client.core.constant.ShenyuClientConstants;
+import 
org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher;
+import org.apache.shenyu.client.core.register.ApiBean;
+import org.apache.shenyu.client.core.register.ClientRegisterConfig;
+import org.apache.shenyu.client.core.utils.ApiBeanUtil;
+import org.apache.shenyu.client.core.utils.OpenApiUtils;
+import org.apache.shenyu.common.enums.ApiHttpMethodEnum;
+import org.apache.shenyu.common.enums.ApiSourceEnum;
+import org.apache.shenyu.common.enums.ApiStateEnum;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.PathUtils;
+import org.apache.shenyu.register.common.dto.ApiDocRegisterDTO;
+import org.apache.shenyu.register.common.enums.EventType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * ApiDocRegistrarImplImpl.
+ *
+ * @see ApiDocRegisterDTO
+ */
+public class ApiDocRegistrarImplImpl extends BaseApiRegistrarImpl {
+    
+    private final ShenyuClientRegisterEventPublisher publisher = 
ShenyuClientRegisterEventPublisher.getInstance();
+    
+    private final ClientRegisterConfig clientRegisterConfig;
+    
+    public ApiDocRegistrarImplImpl(final ClientRegisterConfig 
clientRegisterConfig) {
+        this.clientRegisterConfig = clientRegisterConfig;
+    }
+    
+    @Override
+    protected void doRegisterBean(final ApiBean apiBean) {
+        // no supported
+    }
+    
+    @Override
+    protected void doRegisterApi(final ApiBean.ApiDefinition api) {
+        publisher.publishEvent(ApiDocRegisterDTO.builder()
+                .consume(getConsume(api))
+                .produce(getProduce(api))
+                .httpMethod(getHttpMethod(api))
+                .contextPath(clientRegisterConfig.getContextPath())
+                .document(getDocument(api))
+                .rpcType(getRpcType(api))
+                .version(getVersion(api))
+                .apiDesc(getApiDesc(api))
+                .ext(getExt(api))
+                .tags(buildTags(api))
+                .apiPath(getPath(api))
+                .apiSource(getApiSource(api))
+                .apiOwner(getOwner(api))
+                .state(ApiStateEnum.PUBLISHED.getState())
+                .eventType(EventType.REGISTER)
+                .build());
+    }
+    
+    private static Integer getHttpMethod(final ApiBean.ApiDefinition api) {
+        final String httpMethod = api.getPropertiesValue("httpMethod");
+        if (StringUtils.isNotBlank(httpMethod)) {
+            return Integer.parseInt(httpMethod);
+        }
+        return ApiHttpMethodEnum.NOT_HTTP.getValue();
+    }
+    
+    @NotNull
+    private static String getOwner(final ApiBean.ApiDefinition api) {
+        final String owner = api.getPropertiesValue("owner");
+        if (StringUtils.isNotBlank(owner)) {
+            return owner;
+        }
+        return "admin";
+    }
+    
+    private String getExt(final ApiBean.ApiDefinition api) {
+        final String ext = api.getPropertiesValue("ext");
+        if (StringUtils.isNotBlank(ext)) {
+            return ext;
+        }
+        ApiDocRegisterDTO.ApiExt apiExt = new ApiDocRegisterDTO.ApiExt();
+        
+        apiExt.setHost(clientRegisterConfig.getHost());
+        apiExt.setPort(clientRegisterConfig.getPort());
+        apiExt.setServiceName(api.getApiBean().getBeanClass().getName());
+        apiExt.setMethodName(api.getApiMethodName());
+        apiExt.setParameterTypes(api.getParameterTypes());
+        apiExt.setRpcExt(api.getPropertiesValue("RpcExt"));
+        apiExt.setAddPrefixed(clientRegisterConfig.getAddPrefixed());
+        final String rpcType = getRpcType(api);
+        
+        if (Objects.equals(rpcType, RpcTypeEnum.HTTP.getName())) {
+            apiExt.setProtocol(ShenyuClientConstants.HTTP);
+        }
+        if (Objects.equals(rpcType, RpcTypeEnum.WEB_SOCKET.getName())) {
+            apiExt.setProtocol(ShenyuClientConstants.WS);
+        }
+        
+        return GsonUtils.getInstance().toJson(apiExt);
+    }
+    
+    private String getDocument(final ApiBean.ApiDefinition api) {
+        final String document = api.getPropertiesValue("document");
+        if (StringUtils.isNotBlank(document)) {
+            return document;
+        }
+        final String path = getPath(api);
+        final Map<String, Object> documentMap = ImmutableMap.<String, 
Object>builder()
+                .put("tags", buildTags(api))
+                .put("operationId", path)
+                .put("parameters", 
OpenApiUtils.generateDocumentParameters(path, api.getApiMethod()))
+                .put("responses", 
OpenApiUtils.generateDocumentResponse(path)).build();
+        return GsonUtils.getInstance().toJson(documentMap);
+    }
+    
+    private String getRpcType(final ApiBean.ApiDefinition api) {
+        return ApiBeanUtil.getRpcType(api);
+    }
+    
+    private String getVersion(final ApiBean.ApiDefinition api) {
+        final String version = api.getPropertiesValue("version");
+        if (StringUtils.isNotBlank(version)) {
+            return version;
+        }
+        return "v0.01";
+    }
+    
+    private String getApiDesc(final ApiBean.ApiDefinition api) {
+        final String desc = api.getPropertiesValue("desc");
+        if (StringUtils.isNotBlank(desc)) {
+            return desc;
+        }
+        return api.getApiBean().getClientName()
+                + ":"
+                + api.getApiBean().getBeanClass().getName()
+                + "#"
+                + api.getApiMethod().getName();
+    }
+    
+    private Integer getApiSource(final ApiBean.ApiDefinition apiDefinition) {
+        final String apiSource = apiDefinition.getPropertiesValue("apiSource");
+        if (StringUtils.isNotBlank(apiSource)) {
+            return Integer.parseInt(apiSource);
+        }
+        return ApiSourceEnum.ANNOTATION_GENERATION.getValue();
+    }
+    
+    private String getPath(final ApiBean.ApiDefinition api) {
+        return PathUtils.pathJoin(clientRegisterConfig.getContextPath(), 
api.getApiBean().getBeanPath(), api.getMethodPath());
+    }
+    
+    private String getProduce(final ApiBean.ApiDefinition api) {
+        final String produce = api.getPropertiesValue("produce");
+        if (StringUtils.isNotBlank(produce)) {
+            return ShenyuClientConstants.MEDIA_TYPE_ALL_VALUE;
+        }
+        return produce;
+    }
+    
+    private static String getConsume(final ApiBean.ApiDefinition api) {
+        final String consume = api.getPropertiesValue("consume");
+        if (StringUtils.isNotBlank(consume)) {
+            return ShenyuClientConstants.MEDIA_TYPE_ALL_VALUE;
+        }
+        return consume;
+    }
+    
+    private List<String> buildTags(final ApiBean.ApiDefinition api) {
+        final String tags = api.getPropertiesValue("tags");
+        if (StringUtils.isNotBlank(tags)) {
+            return Arrays.stream(tags.split(","))
+                    .collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/BaseApiRegistrarImpl.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/BaseApiRegistrarImpl.java
new file mode 100644
index 000000000..f8f5af99e
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/BaseApiRegistrarImpl.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.registrar;
+
+import org.apache.shenyu.client.core.register.ApiBean;
+import org.apache.shenyu.client.core.register.matcher.ApiProcessor;
+import org.springframework.beans.factory.InitializingBean;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * BaseApiRegistrarImpl.
+ */
+public abstract class BaseApiRegistrarImpl implements ApiRegistrar, 
InitializingBean {
+    
+    private final List<ApiProcessor> processors = new ArrayList<>();
+    
+    @Override
+    public void afterPropertiesSet() {
+        processors.sort(Comparator.comparingInt(ApiProcessor::order));
+    }
+    
+    /**
+     * add processor.
+     *
+     * @param processor processor
+     */
+    public void addApiProcessor(final ApiProcessor processor) {
+        processors.add(processor);
+        processors.sort(Comparator.comparingInt(ApiProcessor::order));
+    }
+    
+    @Override
+    public void register(final ApiBean apiBean) {
+        for (ApiProcessor processor : processors) {
+            processor.process(apiBean);
+        }
+        if (ApiBean.Status.INIT.equals(apiBean.getStatus())) {
+            // default register all api
+            apiBean.setStatus(ApiBean.Status.REGISTRABLE_API);
+            for (ApiBean.ApiDefinition definition : 
apiBean.getApiDefinitions()) {
+                if (ApiBean.Status.INIT.equals(definition.getStatus())) {
+                    definition.setStatus(ApiBean.Status.REGISTRABLE);
+                }
+            }
+        }
+        doRegister(apiBean);
+    }
+    
+    protected void doRegister(final ApiBean apiBean) {
+        if (ApiBean.Status.REGISTRABLE_BEAN.equals(apiBean.getStatus())) {
+            doRegisterBean(apiBean);
+        }
+        
+        if (ApiBean.Status.REGISTRABLE_API.equals(apiBean.getStatus())) {
+            doRegisterApi(apiBean);
+        }
+        
+        if (ApiBean.Status.REGISTRABLE.equals(apiBean.getStatus())) {
+            doRegisterBean(apiBean);
+            doRegisterApi(apiBean);
+        }
+    }
+    
+    private void doRegisterApi(final ApiBean apiBean) {
+        for (ApiBean.ApiDefinition api : apiBean.getApiDefinitions()) {
+            if (ApiBean.Status.REGISTRABLE.equals(api.getStatus())) {
+                doRegisterApi(api);
+            }
+        }
+    }
+    
+    /**
+     * register api.
+     *
+     * @param api api
+     */
+    protected abstract void doRegisterApi(ApiBean.ApiDefinition api);
+    
+    /**
+     * register bean.
+     *
+     * @param apiBean bean
+     */
+    protected abstract void doRegisterBean(ApiBean apiBean);
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/MateDataApiRegistrarImplImpl.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/MateDataApiRegistrarImplImpl.java
new file mode 100644
index 000000000..94b108f96
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/MateDataApiRegistrarImplImpl.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.registrar;
+
+import org.apache.commons.lang3.StringUtils;
+import 
org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher;
+import org.apache.shenyu.client.core.register.ApiBean;
+import org.apache.shenyu.client.core.register.ClientRegisterConfig;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.common.utils.PathUtils;
+import org.apache.shenyu.register.common.dto.MetaDataRegisterDTO;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * MateDataApiRegistrarImplImpl.
+ *
+ * @see MetaDataRegisterDTO
+ */
+public class MateDataApiRegistrarImplImpl extends BaseApiRegistrarImpl {
+    
+    private final ShenyuClientRegisterEventPublisher publisher = 
ShenyuClientRegisterEventPublisher.getInstance();
+    
+    private final ClientRegisterConfig clientRegisterConfig;
+    
+    public MateDataApiRegistrarImplImpl(final ClientRegisterConfig 
clientRegisterConfig) {
+        this.clientRegisterConfig = clientRegisterConfig;
+    }
+    
+    @Override
+    protected void doRegisterApi(final ApiBean.ApiDefinition api) {
+        final MetaDataRegisterDTO metaDataRegisterDTO = 
MetaDataRegisterDTO.builder()
+                .contextPath(clientRegisterConfig.getContextPath())
+                .addPrefixed(clientRegisterConfig.getAddPrefixed())
+                .appName(clientRegisterConfig.getAppName())
+                .serviceName(api.getBeanClass().getName())
+                .host(clientRegisterConfig.getHost())
+                .port(clientRegisterConfig.getPort())
+                .methodName(api.getApiMethodName())
+                .path(buildPath(api))
+                .pathDesc(buildDesc(api))
+                .parameterTypes(buildParameterTypes(api))
+                .rpcType(RpcTypeEnum.SPRING_CLOUD.getName())
+                .enabled(getEnable(api))
+                .ruleName(buildRule(api))
+                .build();
+        
+        register(metaDataRegisterDTO);
+    }
+    
+    @Override
+    protected void doRegisterBean(final ApiBean apiBean) {
+        final MetaDataRegisterDTO metaDataRegisterDTO = 
MetaDataRegisterDTO.builder()
+                .contextPath(clientRegisterConfig.getContextPath())
+                .addPrefixed(clientRegisterConfig.getAddPrefixed())
+                .appName(clientRegisterConfig.getAppName())
+                .serviceName(apiBean.getBeanClass().getName())
+                .host(clientRegisterConfig.getHost())
+                .port(clientRegisterConfig.getPort())
+                .methodName(apiBean.getBeanClass().getSimpleName())
+                .path(buildPath(apiBean))
+                .pathDesc(buildDesc(apiBean))
+                .parameterTypes(buildParameterTypes(apiBean))
+                .rpcType(RpcTypeEnum.SPRING_CLOUD.getName())
+                .enabled(getEnable(apiBean))
+                .ruleName(buildRule(apiBean))
+                .build();
+        
+        register(metaDataRegisterDTO);
+    }
+    
+    private String buildParameterTypes(final ApiBean api) {
+        final String parameterTypes = api.getPropertiesValue("parameterTypes");
+        if (StringUtils.isNotBlank(parameterTypes)) {
+            return parameterTypes;
+        }
+        return null;
+    }
+    
+    private String buildParameterTypes(final ApiBean.ApiDefinition api) {
+        final String parameterTypes = api.getPropertiesValue("parameterTypes");
+        if (StringUtils.isNotBlank(parameterTypes)) {
+            return parameterTypes;
+        }
+        return null;
+    }
+    
+    private String buildRule(@NotNull final ApiBean api) {
+        final String rule = api.getPropertiesValue("rule");
+        if (StringUtils.isNotBlank(rule)) {
+            return rule;
+        }
+        return StringUtils.defaultIfBlank("", buildPath(api));
+    }
+    
+    private String buildRule(@NotNull final ApiBean.ApiDefinition api) {
+        final String rule = api.getPropertiesValue("rule");
+        if (StringUtils.isNotBlank(rule)) {
+            return rule;
+        }
+        return StringUtils.defaultIfBlank("", buildPath(api));
+    }
+    
+    private boolean getEnable(final ApiBean api) {
+        final String enable = api.getPropertiesValue("enable");
+        if (StringUtils.isNotBlank(enable)) {
+            return Boolean.parseBoolean(enable);
+        }
+        return true;
+    }
+    
+    private boolean getEnable(final ApiBean.ApiDefinition api) {
+        final String enable = api.getPropertiesValue("enable");
+        if (StringUtils.isNotBlank(enable)) {
+            return Boolean.parseBoolean(enable);
+        }
+        return true;
+    }
+    
+    private String buildDesc(final ApiBean api) {
+        final String desc = api.getPropertiesValue("desc");
+        if (StringUtils.isNotBlank(desc)) {
+            return desc;
+        }
+        return api.getClientName()
+                + ":"
+                + api.getBeanClass().getName()
+                + "#*";
+    }
+    
+    private String buildDesc(final ApiBean.ApiDefinition api) {
+        final String desc = api.getPropertiesValue("desc");
+        if (StringUtils.isNotBlank(desc)) {
+            return desc;
+        }
+        return api.getApiBean().getClientName()
+                + ":"
+                + api.getApiBean().getBeanClass().getName()
+                + "#"
+                + api.getApiMethod().getName();
+    }
+    
+    private String buildPath(final ApiBean api) {
+        return PathUtils.pathJoin(clientRegisterConfig.getContextPath(), 
api.getBeanPath());
+    }
+    
+    private String buildPath(final ApiBean.ApiDefinition api) {
+        return PathUtils.pathJoin(clientRegisterConfig.getContextPath(), 
api.getApiBean().getBeanPath(), api.getMethodPath());
+    }
+    
+    private void register(final MetaDataRegisterDTO metaDataRegisterDTO) {
+        publisher.publishEvent(metaDataRegisterDTO);
+    }
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/UriApiRegistrarImplImpl.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/UriApiRegistrarImplImpl.java
new file mode 100644
index 000000000..c98742880
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/register/registrar/UriApiRegistrarImplImpl.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.register.registrar;
+
+import 
org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher;
+import org.apache.shenyu.client.core.register.ApiBean;
+import org.apache.shenyu.client.core.register.ClientRegisterConfig;
+import org.apache.shenyu.client.core.utils.ApiBeanUtil;
+import org.apache.shenyu.register.common.dto.URIRegisterDTO;
+import org.apache.shenyu.register.common.enums.EventType;
+
+/**
+ * UriApiRegistrarImplImpl.
+ *
+ * @see URIRegisterDTO
+ */
+public class UriApiRegistrarImplImpl extends BaseApiRegistrarImpl {
+    
+    private final ShenyuClientRegisterEventPublisher publisher = 
ShenyuClientRegisterEventPublisher.getInstance();
+    
+    private final ClientRegisterConfig clientRegisterConfig;
+    
+    public UriApiRegistrarImplImpl(final ClientRegisterConfig 
clientRegisterConfig) {
+        this.clientRegisterConfig = clientRegisterConfig;
+    }
+    
+    @Override
+    protected void doRegisterApi(final ApiBean.ApiDefinition api) {
+        final URIRegisterDTO uriRegisterDTO = URIRegisterDTO.builder()
+                .contextPath(clientRegisterConfig.getContextPath())
+                .appName(clientRegisterConfig.getAppName())
+                .eventType(EventType.REGISTER)
+                .host(clientRegisterConfig.getHost())
+                .port(clientRegisterConfig.getPort())
+                .rpcType(getRpcType(api))
+                .build();
+        publisher.publishEvent(uriRegisterDTO);
+    }
+    
+    @Override
+    protected void doRegisterBean(final ApiBean apiBean) {
+        final URIRegisterDTO uriRegisterDTO = URIRegisterDTO.builder()
+                .contextPath(clientRegisterConfig.getContextPath())
+                .appName(clientRegisterConfig.getAppName())
+                .eventType(EventType.REGISTER)
+                .host(clientRegisterConfig.getHost())
+                .port(clientRegisterConfig.getPort())
+                .rpcType(getRpcType(apiBean))
+                .build();
+        publisher.publishEvent(uriRegisterDTO);
+    }
+    
+    private static String getRpcType(final ApiBean.ApiDefinition api) {
+        return ApiBeanUtil.getRpcType(api);
+    }
+    
+    private static String getRpcType(final ApiBean api) {
+        return ApiBeanUtil.getRpcType(api);
+    }
+    
+}
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/ApiBeanUtil.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/ApiBeanUtil.java
new file mode 100644
index 000000000..ad4ca141a
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/ApiBeanUtil.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.core.utils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.client.core.register.ApiBean;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+
+import java.util.Objects;
+
+/**
+ * ApiBeanUtil.
+ */
+public final class ApiBeanUtil {
+    
+    private ApiBeanUtil() {
+    
+    }
+    
+    /**
+     * get rpc type.
+     *
+     * @param api api
+     * @return rpc type
+     */
+    public static String getRpcType(final ApiBean.ApiDefinition api) {
+        final String rpcType = api.getPropertiesValue("rpcType");
+        if (StringUtils.isBlank(rpcType)) {
+            for (RpcTypeEnum value : RpcTypeEnum.values()) {
+                if (Objects.equals(value.getName(), 
api.getApiBean().getClientName())) {
+                    return value.getName();
+                }
+            }
+            return "unknown";
+        }
+        return rpcType;
+    }
+    
+    /**
+     * get rpc type.
+     *
+     * @param api api
+     * @return rpc type
+     */
+    public static String getRpcType(final ApiBean api) {
+        final String rpcType = api.getPropertiesValue("rpcType");
+        if (StringUtils.isBlank(rpcType)) {
+            for (RpcTypeEnum value : RpcTypeEnum.values()) {
+                if (Objects.equals(value.getName(), api.getClientName())) {
+                    return value.getName();
+                }
+            }
+            return "unknown";
+        }
+        return rpcType;
+    }
+    
+}
diff --git 
a/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/register/SpringCloudApiBeansExtractor.java
 
b/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/register/SpringCloudApiBeansExtractor.java
index 782d6c98b..ce55cec1e 100644
--- 
a/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/register/SpringCloudApiBeansExtractor.java
+++ 
b/shenyu-client/shenyu-client-http/shenyu-client-springcloud/src/main/java/org/apache/shenyu/client/springcloud/register/SpringCloudApiBeansExtractor.java
@@ -66,6 +66,11 @@ public class SpringCloudApiBeansExtractor extends 
BaseAnnotationApiBeansExtracto
         // rewrite api path
         api.setBeanPath(beanPath);
         
+        if (Objects.nonNull(requestMapping)) {
+            api.addProperties("consumes", String.join(",", 
requestMapping.consumes()));
+            api.addProperties("produces", String.join(",", 
requestMapping.produces()));
+        }
+        
         // Get additional values from the annotation.
         super.apiPostProcess(api);
     }
@@ -78,6 +83,9 @@ public class SpringCloudApiBeansExtractor extends 
BaseAnnotationApiBeansExtracto
         // rewrite api path
         apiDefinition.setMethodPath(getPath(requestMapping));
         
+        apiDefinition.addProperties("consumes", String.join(",", 
requestMapping.consumes()));
+        apiDefinition.addProperties("produces", String.join(",", 
requestMapping.produces()));
+        
         // Get additional values from the annotation.
         super.definitionPostProcess(apiDefinition);
     }
diff --git 
a/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/register/ShenyuSpringMvcClientProcessorImpl.java
 
b/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/register/ShenyuSpringMvcClientProcessorImpl.java
new file mode 100644
index 000000000..d03c16df7
--- /dev/null
+++ 
b/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/register/ShenyuSpringMvcClientProcessorImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.client.springmvc.register;
+
+import org.apache.shenyu.client.core.register.ApiBean;
+import 
org.apache.shenyu.client.core.register.matcher.BaseAnnotationApiProcessor;
+import org.apache.shenyu.client.springmvc.annotation.ShenyuSpringMvcClient;
+
+import java.util.Objects;
+
+/**
+ * RequestMappingProcessorImpl.<br>
+ * About support for {@link ShenyuSpringMvcClient} annotations
+ *
+ * @see ShenyuSpringMvcClient
+ */
+public class ShenyuSpringMvcClientProcessorImpl extends 
BaseAnnotationApiProcessor<ShenyuSpringMvcClient> {
+    
+    @Override
+    protected void process(final ApiBean apiBean, final ShenyuSpringMvcClient 
annotation) {
+        apiBean.setBeanPath(annotation.path());
+        apiBean.addProperties("desc", annotation.desc());
+        apiBean.addProperties("rule", annotation.ruleName());
+        apiBean.addProperties("value", annotation.value());
+        apiBean.addProperties("enabled", 
Objects.toString(annotation.enabled()));
+        apiBean.addProperties("registerMetaData", 
Objects.toString(annotation.registerMetaData()));
+        if (!annotation.registerMetaData()) {
+            apiBean.setStatus(ApiBean.Status.CAN_NO_BE_REGISTERED);
+        } else {
+            apiBean.setStatus(ApiBean.Status.REGISTRABLE_API);
+        }
+    }
+    
+    @Override
+    protected void process(final ApiBean.ApiDefinition definition, final 
ShenyuSpringMvcClient annotation) {
+        definition.setMethodPath(annotation.path());
+        definition.addProperties("desc", annotation.desc());
+        definition.addProperties("rule", annotation.ruleName());
+        definition.addProperties("value", annotation.value());
+        definition.addProperties("enabled", 
Objects.toString(annotation.enabled()));
+        definition.addProperties("registerMetaData", 
Objects.toString(annotation.registerMetaData()));
+        if (!annotation.registerMetaData()) {
+            definition.setStatus(ApiBean.Status.CAN_NO_BE_REGISTERED);
+        } else {
+            definition.setStatus(ApiBean.Status.REGISTRABLE);
+        }
+    }
+    
+    @Override
+    protected Class<ShenyuSpringMvcClient> matchAnnotation() {
+        return ShenyuSpringMvcClient.class;
+    }
+}


Reply via email to