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;
+ }
+}