You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by zh...@apache.org on 2022/12/08 06:18:29 UTC
[shenyu] branch master updated: [ISSUE #3450]Add brpc-client&starter-client-brpc (#4149)
This is an automated email from the ASF dual-hosted git repository.
zhangzicheng 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 8b1f8608e [ISSUE #3450]Add brpc-client&starter-client-brpc (#4149)
8b1f8608e is described below
commit 8b1f8608ef8f20c17d3157998353eb3ed18dd324
Author: SongTao Zhuang <51...@users.noreply.github.com>
AuthorDate: Thu Dec 8 14:18:22 2022 +0800
[ISSUE #3450]Add brpc-client&starter-client-brpc (#4149)
* add: brpc client
* add: brpc plugin enum
* add: license header
* pom: starlight stable version
Co-authored-by: dragon-zhang <zh...@apache.org>
---
pom.xml | 1 +
shenyu-client/pom.xml | 1 +
shenyu-client/{ => shenyu-client-brpc}/pom.xml | 40 ++---
.../brpc/BrpcContextRefreshedEventListener.java | 161 +++++++++++++++++++++
.../brpc/common/annotation/ShenyuBrpcClient.java | 72 +++++++++
.../shenyu/client/brpc/common/dto/BrpcRpcExt.java | 145 +++++++++++++++++++
.../client/brpc/BrpcClientEventListenerTest.java | 117 +++++++++++++++
.../org/apache/shenyu/common/enums/PluginEnum.java | 5 +
.../apache/shenyu/common/enums/RpcTypeEnum.java | 6 +-
.../shenyu/common/utils/PluginNameAdapter.java | 2 +
.../shenyu-spring-boot-starter-client/pom.xml | 1 +
.../pom.xml | 42 +++---
.../client/brpc/ShenyuBrpcClientConfiguration.java | 49 +++++++
.../src/main/resources/META-INF/spring.factories | 19 +++
.../src/main/resources/META-INF/spring.provides | 18 +++
.../brpc/ShenyuBrpcClientConfigurationTest.java | 73 ++++++++++
16 files changed, 703 insertions(+), 49 deletions(-)
diff --git a/pom.xml b/pom.xml
index 9eb182996..0d8c4ae20 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,6 +125,7 @@
<nacos-client.version>2.0.4</nacos-client.version>
<spring-security.version>5.3.10.RELEASE</spring-security.version>
<grpc.version>1.33.1</grpc.version>
+ <brpc.version>2022.2.0</brpc.version>
<rocketmq-client.version>4.9.3</rocketmq-client.version>
<pulsar-client.version>2.10.1</pulsar-client.version>
<lz4-java.version>1.8.0</lz4-java.version>
diff --git a/shenyu-client/pom.xml b/shenyu-client/pom.xml
index 93965453d..7f669abe8 100644
--- a/shenyu-client/pom.xml
+++ b/shenyu-client/pom.xml
@@ -35,6 +35,7 @@
<module>shenyu-client-grpc</module>
<module>shenyu-client-motan</module>
<module>shenyu-client-websocket</module>
+ <module>shenyu-client-brpc</module>
</modules>
<dependencies>
diff --git a/shenyu-client/pom.xml b/shenyu-client/shenyu-client-brpc/pom.xml
similarity index 52%
copy from shenyu-client/pom.xml
copy to shenyu-client/shenyu-client-brpc/pom.xml
index 93965453d..c649a2c95 100644
--- a/shenyu-client/pom.xml
+++ b/shenyu-client/shenyu-client-brpc/pom.xml
@@ -16,42 +16,34 @@
~ limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.shenyu</groupId>
- <artifactId>shenyu</artifactId>
+ <artifactId>shenyu-client</artifactId>
<version>2.5.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>shenyu-client</artifactId>
- <packaging>pom</packaging>
-
- <modules>
- <module>shenyu-client-core</module>
- <module>shenyu-client-http</module>
- <module>shenyu-client-dubbo</module>
- <module>shenyu-client-sofa</module>
- <module>shenyu-client-tars</module>
- <module>shenyu-client-grpc</module>
- <module>shenyu-client-motan</module>
- <module>shenyu-client-websocket</module>
- </modules>
+
+ <artifactId>shenyu-client-brpc</artifactId>
<dependencies>
<dependency>
- <groupId>com.squareup.okhttp3</groupId>
- <artifactId>okhttp</artifactId>
- <version>${okhttp.version}</version>
+ <groupId>org.apache.shenyu</groupId>
+ <artifactId>shenyu-client-core</artifactId>
+ <version>${project.version}</version>
</dependency>
+
<dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>${gson.version}</version>
+ <groupId>com.baidu.cloud</groupId>
+ <artifactId>spring-cloud-starter-baidu-starlight</artifactId>
+ <version>2022.2.0</version>
</dependency>
<dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/BrpcContextRefreshedEventListener.java b/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/BrpcContextRefreshedEventListener.java
new file mode 100644
index 000000000..9dbb06285
--- /dev/null
+++ b/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/BrpcContextRefreshedEventListener.java
@@ -0,0 +1,161 @@
+/*
+ * 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.brpc;
+
+import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.shenyu.client.brpc.common.annotation.ShenyuBrpcClient;
+import org.apache.shenyu.client.brpc.common.dto.BrpcRpcExt;
+import org.apache.shenyu.client.core.client.AbstractContextRefreshedEventListener;
+import org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.IpUtils;
+import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository;
+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.springframework.context.ApplicationContext;
+import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
+import org.springframework.util.ReflectionUtils;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * The type Brpc context refreshed event listener.
+ */
+public class BrpcContextRefreshedEventListener extends AbstractContextRefreshedEventListener<Object, ShenyuBrpcClient> {
+
+ private final LocalVariableTableParameterNameDiscoverer localVariableTableParameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
+
+ private final ShenyuClientRegisterEventPublisher publisher = ShenyuClientRegisterEventPublisher.getInstance();
+
+ private ApplicationContext applicationContext;
+
+ /**
+ * Instantiates a new Brpc context refreshed event listener.
+ *
+ * @param clientConfig the client config
+ * @param shenyuClientRegisterRepository the shenyuClientRegisterRepository
+ */
+ public BrpcContextRefreshedEventListener(final PropertiesConfig clientConfig,
+ final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+ super(clientConfig, shenyuClientRegisterRepository);
+ }
+
+ @Override
+ protected Map<String, Object> getBeans(final ApplicationContext context) {
+ applicationContext = context;
+ return context.getBeansWithAnnotation(ShenyuBrpcClient.class);
+ }
+
+ @Override
+ protected URIRegisterDTO buildURIRegisterDTO(final ApplicationContext context, final Map<String, Object> beans) {
+ return URIRegisterDTO.builder()
+ .contextPath(this.getContextPath())
+ .appName(this.getAppName())
+ .rpcType(RpcTypeEnum.BRPC.getName())
+ .host(this.getHost())
+ .port(Integer.parseInt(this.getPort()))
+ .build();
+ }
+
+ @Override
+ protected String buildApiSuperPath(final Class<?> clazz, final ShenyuBrpcClient shenyuBrpcClient) {
+ if (Objects.nonNull(shenyuBrpcClient) && !StringUtils.isBlank(shenyuBrpcClient.path())) {
+ return shenyuBrpcClient.path();
+ }
+ return "";
+ }
+
+ @Override
+ protected Class<ShenyuBrpcClient> getAnnotationType() {
+ return ShenyuBrpcClient.class;
+ }
+
+ @Override
+ protected String buildApiPath(final Method method, final String superPath, final ShenyuBrpcClient shenyuBrpcClient) {
+ return superPath.contains("*")
+ ? pathJoin(this.getContextPath(), superPath.replace("*", ""), method.getName())
+ : pathJoin(this.getContextPath(), superPath, shenyuBrpcClient.path());
+ }
+
+ @Override
+ protected void handleClass(final Class<?> clazz, final Object bean, final ShenyuBrpcClient shenyuBrpcClient, final String superPath) {
+ Method[] methods = ReflectionUtils.getDeclaredMethods(clazz);
+ for (Method method : methods) {
+ publisher.publishEvent(buildMetaDataDTO(bean, shenyuBrpcClient, superPath, clazz, method));
+ }
+ }
+
+ @Override
+ protected MetaDataRegisterDTO buildMetaDataDTO(final Object bean, final ShenyuBrpcClient shenyuBrpcClient, final String superPath, final Class<?> clazz, final Method method) {
+ String serviceName = clazz.getAnnotation(RpcService.class).serviceId();
+ String path = shenyuBrpcClient.path();
+ String desc = shenyuBrpcClient.desc();
+ String host = IpUtils.isCompleteHost(this.getHost()) ? this.getHost() : IpUtils.getHost(this.getHost());
+ String configRuleName = shenyuBrpcClient.ruleName();
+ String ruleName = ("".equals(configRuleName)) ? path : configRuleName;
+ int port = StringUtils.isBlank(this.getPort()) ? -1 : Integer.parseInt(this.getPort());
+ String methodName = method.getName();
+ Class<?>[] parameterTypesClazz = method.getParameterTypes();
+ String parameterTypes = Arrays.stream(parameterTypesClazz).map(Class::getName)
+ .collect(Collectors.joining(","));
+ return MetaDataRegisterDTO.builder()
+ .appName(this.getAppName())
+ .serviceName(serviceName)
+ .methodName(methodName)
+ .contextPath(this.getContextPath())
+ .path(path)
+ .port(port)
+ .host(host)
+ .pathDesc(desc)
+ .ruleName(ruleName)
+ .parameterTypes(parameterTypes)
+ .rpcType(RpcTypeEnum.BRPC.getName())
+ .rpcExt(buildRpcExt(method))
+ .enabled(shenyuBrpcClient.enabled())
+ .build();
+ }
+
+ private String buildRpcExt(final Method method) {
+ List<BrpcRpcExt.RpcExt> list = new ArrayList<>();
+ list.add(build(method));
+ BrpcRpcExt buildList = new BrpcRpcExt(list);
+ return GsonUtils.getInstance().toJson(buildList);
+ }
+
+ private BrpcRpcExt.RpcExt build(final Method method) {
+ String[] paramNames = localVariableTableParameterNameDiscoverer.getParameterNames(method);
+ List<Pair<String, String>> params = new ArrayList<>();
+ if (paramNames != null && paramNames.length > 0) {
+ Class<?>[] paramTypes = method.getParameterTypes();
+ for (int i = 0; i < paramNames.length; i++) {
+ params.add(Pair.of(paramTypes[i].getName(), paramNames[i]));
+ }
+ }
+ return new BrpcRpcExt.RpcExt(method.getName(), params);
+ }
+}
diff --git a/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/common/annotation/ShenyuBrpcClient.java b/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/common/annotation/ShenyuBrpcClient.java
new file mode 100644
index 000000000..994026ba5
--- /dev/null
+++ b/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/common/annotation/ShenyuBrpcClient.java
@@ -0,0 +1,72 @@
+/*
+ * 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.brpc.common.annotation;
+
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The interface shenyu client.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Inherited
+public @interface ShenyuBrpcClient {
+
+ /**
+ * Value string.
+ *
+ * @return the string
+ */
+ @AliasFor(attribute = "path")
+ String value() default "";
+
+ /**
+ * Path string.
+ *
+ * @return the string
+ */
+ @AliasFor(attribute = "value")
+ String path() default "";
+
+ /**
+ * Rule name string.
+ *
+ * @return the string
+ */
+ String ruleName() default "";
+
+ /**
+ * Desc string.
+ *
+ * @return String string
+ */
+ String desc() default "";
+
+ /**
+ * Enabled boolean.
+ *
+ * @return the boolean
+ */
+ boolean enabled() default true;
+}
diff --git a/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/common/dto/BrpcRpcExt.java b/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/common/dto/BrpcRpcExt.java
new file mode 100644
index 000000000..07b82bb72
--- /dev/null
+++ b/shenyu-client/shenyu-client-brpc/src/main/java/org/apache/shenyu/client/brpc/common/dto/BrpcRpcExt.java
@@ -0,0 +1,145 @@
+/*
+ * 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.brpc.common.dto;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.List;
+
+/**
+ * Brpc rpc ext.
+ */
+public class BrpcRpcExt {
+
+ /**
+ * in order to be compatible with the old version,
+ * we can't change the type of this field.
+ */
+ private List<RpcExt> methodInfo;
+
+ /**
+ * constructor without params.
+ */
+ public BrpcRpcExt() {
+ }
+
+ /**
+ * constructor with all params.
+ *
+ * @param methodInfo methodInfo
+ */
+ public BrpcRpcExt(final List<RpcExt> methodInfo) {
+ this.methodInfo = methodInfo;
+ }
+
+ /**
+ * get methodInfo.
+ *
+ * @return methodInfo
+ */
+ public List<RpcExt> getMethodInfo() {
+ return methodInfo;
+ }
+
+ /**
+ * set methodInfo.
+ *
+ * @param methodInfo methodInfo
+ */
+ public void setMethodInfo(final List<RpcExt> methodInfo) {
+ this.methodInfo = methodInfo;
+ }
+
+ @Override
+ public String toString() {
+ return "BrpcRpcExt{"
+ + "methodInfo=" + methodInfo
+ + '}';
+ }
+
+ /**
+ * The type Rpc ext.
+ */
+ public static class RpcExt {
+
+ private String methodName;
+
+ private List<Pair<String, String>> paramTypes;
+
+ /**
+ * constructor without params.
+ */
+ public RpcExt() {
+ }
+
+ /**
+ * constructor with params.
+ *
+ * @param methodName methodName
+ * @param paramTypes params
+ */
+ public RpcExt(final String methodName, final List<Pair<String, String>> paramTypes) {
+ this.methodName = methodName;
+ this.paramTypes = paramTypes;
+ }
+
+ /**
+ * get methodName.
+ *
+ * @return methodName
+ */
+ public String getMethodName() {
+ return methodName;
+ }
+
+ /**
+ * set methodName.
+ *
+ * @param methodName methodName
+ */
+ public void setMethodName(final String methodName) {
+ this.methodName = methodName;
+ }
+
+ /**
+ * get param types.
+ *
+ * @return param types.
+ */
+ public List<Pair<String, String>> getParamTypes() {
+ return paramTypes;
+ }
+
+ /**
+ * set param types.
+ *
+ * @param paramTypes param types
+ */
+ public void setParamTypes(final List<Pair<String, String>> paramTypes) {
+ this.paramTypes = paramTypes;
+ }
+
+ @Override
+ public String toString() {
+ return "RpcExt{"
+ + "methodName='" + methodName + '\''
+ + ", paramTypes=" + paramTypes
+ + '}';
+ }
+ }
+}
diff --git a/shenyu-client/shenyu-client-brpc/src/test/java/org/apache/shenyu/client/brpc/BrpcClientEventListenerTest.java b/shenyu-client/shenyu-client-brpc/src/test/java/org/apache/shenyu/client/brpc/BrpcClientEventListenerTest.java
new file mode 100644
index 000000000..815a7056b
--- /dev/null
+++ b/shenyu-client/shenyu-client-brpc/src/test/java/org/apache/shenyu/client/brpc/BrpcClientEventListenerTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.brpc;
+
+import com.baidu.cloud.starlight.springcloud.server.annotation.RpcService;
+import org.apache.shenyu.client.brpc.common.annotation.ShenyuBrpcClient;
+import org.apache.shenyu.client.core.register.ShenyuClientRegisterRepositoryFactory;
+import org.apache.shenyu.register.client.http.utils.RegisterUtils;
+import org.apache.shenyu.register.common.config.PropertiesConfig;
+import org.apache.shenyu.register.common.config.ShenyuRegisterCenterConfig;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.stubbing.Answer;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.event.ContextRefreshedEvent;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test for {@link BrpcClientEventListenerTest}.
+ */
+@ExtendWith(MockitoExtension.class)
+public class BrpcClientEventListenerTest {
+
+ private final MockedStatic<RegisterUtils> registerUtilsMockedStatic = mockStatic(RegisterUtils.class);
+
+ private final BrpcClientTestBean brpcClientTestBean = new BrpcClientTestBean();
+
+ @Mock
+ private ApplicationContext applicationContext;
+
+ private ContextRefreshedEvent contextRefreshedEvent;
+
+ @BeforeEach
+ public void init() {
+ Map<String, Object> results = new LinkedHashMap<>();
+ results.put("brpcClientTestBean", brpcClientTestBean);
+ when(applicationContext.getBeansWithAnnotation(any())).thenReturn(results);
+ contextRefreshedEvent = new ContextRefreshedEvent(applicationContext);
+ }
+
+ @Test
+ public void testNormalBeanProcess() {
+ registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.of("token"));
+ BrpcContextRefreshedEventListener springMvcClientEventListener = buildBrpcClientEventListener();
+ springMvcClientEventListener.onApplicationEvent(contextRefreshedEvent);
+ verify(applicationContext, times(1)).getBeansWithAnnotation(any());
+ registerUtilsMockedStatic.close();
+ }
+
+ @Test
+ public void testWithShenyuClientAnnotation() {
+ registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.of("token"));
+ registerUtilsMockedStatic.when(() -> RegisterUtils.doRegister(any(), any(), any()))
+ .thenAnswer((Answer<Void>) invocation -> null);
+ BrpcContextRefreshedEventListener springMvcClientEventListener = buildBrpcClientEventListener();
+ springMvcClientEventListener.onApplicationEvent(contextRefreshedEvent);
+ verify(applicationContext, times(1)).getBeansWithAnnotation(any());
+ registerUtilsMockedStatic.close();
+ }
+
+ private BrpcContextRefreshedEventListener buildBrpcClientEventListener() {
+ Properties properties = new Properties();
+ properties.setProperty("appName", "brpc");
+ properties.setProperty("contextPath", "/brpc");
+ properties.setProperty("ipAndPort", "127.0.0.1:21715");
+ properties.setProperty("host", "127.0.0.1");
+ properties.setProperty("port", "21715");
+ properties.setProperty("username", "admin");
+ properties.setProperty("password", "123456");
+ PropertiesConfig config = new PropertiesConfig();
+ config.setProps(properties);
+ ShenyuRegisterCenterConfig mockRegisterCenter = new ShenyuRegisterCenterConfig();
+ mockRegisterCenter.setServerLists("http://127.0.0.1:9095");
+ mockRegisterCenter.setRegisterType("http");
+ mockRegisterCenter.setProps(properties);
+ return new BrpcContextRefreshedEventListener(config, ShenyuClientRegisterRepositoryFactory.newInstance(mockRegisterCenter));
+ }
+
+ @RpcService
+ static class BrpcClientTestBean {
+
+ @ShenyuBrpcClient("/hello")
+ public String hello(final String input) {
+ return "hello:" + input;
+ }
+ }
+
+}
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java
index ab21df89a..05a0c8b41 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java
@@ -237,6 +237,11 @@ public enum PluginEnum {
*/
MOTAN(310, 0, "motan"),
+ /**
+ * Motan plugin enum.
+ */
+ BRPC(310, 0, "brpc"),
+
/**
* Cryptor response plugin enum.
*/
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java
index 572aee40f..4785fe276 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/RpcTypeEnum.java
@@ -66,8 +66,12 @@ public enum RpcTypeEnum {
/**
* grpc.
*/
- GRPC("grpc", true);
+ GRPC("grpc", true),
+ /**
+ * brpc.
+ */
+ BRPC("brpc", true);
private final String name;
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/PluginNameAdapter.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/PluginNameAdapter.java
index 146768bd7..a82e8ba76 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/PluginNameAdapter.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/PluginNameAdapter.java
@@ -48,6 +48,8 @@ public class PluginNameAdapter {
return PluginEnum.WEB_SOCKET.getName();
case MOTAN:
return PluginEnum.MOTAN.getName();
+ case BRPC:
+ return PluginEnum.BRPC.getName();
case HTTP:
default:
return PluginEnum.DIVIDE.getName();
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml
index 84535744a..e70a80d46 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/pom.xml
@@ -37,5 +37,6 @@
<module>shenyu-spring-boot-starter-client-common</module>
<module>shenyu-spring-boot-starter-client-motan</module>
<module>shenyu-spring-boot-starter-client-spring-websocket</module>
+ <module>shenyu-spring-boot-starter-client-brpc</module>
</modules>
</project>
diff --git a/shenyu-client/pom.xml b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/pom.xml
similarity index 52%
copy from shenyu-client/pom.xml
copy to shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/pom.xml
index 93965453d..0f95cfba3 100644
--- a/shenyu-client/pom.xml
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/pom.xml
@@ -16,42 +16,36 @@
~ limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
+ <artifactId>shenyu-spring-boot-starter-client</artifactId>
<groupId>org.apache.shenyu</groupId>
- <artifactId>shenyu</artifactId>
<version>2.5.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>shenyu-client</artifactId>
- <packaging>pom</packaging>
-
- <modules>
- <module>shenyu-client-core</module>
- <module>shenyu-client-http</module>
- <module>shenyu-client-dubbo</module>
- <module>shenyu-client-sofa</module>
- <module>shenyu-client-tars</module>
- <module>shenyu-client-grpc</module>
- <module>shenyu-client-motan</module>
- <module>shenyu-client-websocket</module>
- </modules>
+ <artifactId>shenyu-spring-boot-starter-client-brpc</artifactId>
<dependencies>
<dependency>
- <groupId>com.squareup.okhttp3</groupId>
- <artifactId>okhttp</artifactId>
- <version>${okhttp.version}</version>
+ <groupId>org.apache.shenyu</groupId>
+ <artifactId>shenyu-client-brpc</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>${gson.version}</version>
+ <groupId>org.apache.shenyu</groupId>
+ <artifactId>shenyu-spring-boot-starter-client-common</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/java/org/apache/shenyu/springboot/starter/client/brpc/ShenyuBrpcClientConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/java/org/apache/shenyu/springboot/starter/client/brpc/ShenyuBrpcClientConfiguration.java
new file mode 100644
index 000000000..c352de42f
--- /dev/null
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/java/org/apache/shenyu/springboot/starter/client/brpc/ShenyuBrpcClientConfiguration.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.springboot.starter.client.brpc;
+
+import org.apache.shenyu.client.brpc.BrpcContextRefreshedEventListener;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository;
+import org.apache.shenyu.register.common.config.ShenyuClientConfig;
+import org.apache.shenyu.springboot.starter.client.common.config.ShenyuClientCommonBeanConfiguration;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * The type shenyu brpc client configuration.
+ */
+@Configuration
+@ImportAutoConfiguration(ShenyuClientCommonBeanConfiguration.class)
+@ConditionalOnProperty(value = "shenyu.register.enabled", matchIfMissing = true, havingValue = "true")
+public class ShenyuBrpcClientConfiguration {
+
+ /**
+ * Brpc context refreshed event listener.
+ *
+ * @param clientConfig the client config
+ * @param shenyuClientRegisterRepository the shenyuClientRegisterRepository
+ * @return the brpc context refreshed event listener
+ */
+ @Bean
+ public BrpcContextRefreshedEventListener brpcContextRefreshedEventListener(final ShenyuClientConfig clientConfig, final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+ return new BrpcContextRefreshedEventListener(clientConfig.getClient().get(RpcTypeEnum.BRPC.getName()), shenyuClientRegisterRepository);
+ }
+}
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/resources/META-INF/spring.factories b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..4a3e943af
--- /dev/null
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.apache.shenyu.springboot.starter.client.brpc.ShenyuBrpcClientConfiguration
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/resources/META-INF/spring.provides b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/resources/META-INF/spring.provides
new file mode 100644
index 000000000..aa38dbf21
--- /dev/null
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/main/resources/META-INF/spring.provides
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+provides: shenyu-spring-boot-starter-client-brpc
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/test/java/org/apache/shenyu/springboot/starter/client/brpc/ShenyuBrpcClientConfigurationTest.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/test/java/org/apache/shenyu/springboot/starter/client/brpc/ShenyuBrpcClientConfigurationTest.java
new file mode 100644
index 000000000..1bcf6db6b
--- /dev/null
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-brpc/src/test/java/org/apache/shenyu/springboot/starter/client/brpc/ShenyuBrpcClientConfigurationTest.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.springboot.starter.client.brpc;
+
+import org.apache.shenyu.client.brpc.BrpcContextRefreshedEventListener;
+import org.apache.shenyu.register.client.http.utils.RegisterUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mockStatic;
+
+/**
+ * Test case for {@link ShenyuBrpcClientConfiguration}.
+ */
+@Configuration
+@EnableConfigurationProperties
+public class ShenyuBrpcClientConfigurationTest {
+
+ private ApplicationContextRunner applicationContextRunner;
+
+ @BeforeEach
+ public void before() {
+ applicationContextRunner = new ApplicationContextRunner()
+ .withConfiguration(AutoConfigurations.of(ShenyuBrpcClientConfiguration.class))
+ .withBean(ShenyuBrpcClientConfigurationTest.class)
+ .withPropertyValues(
+ "debug=true",
+ "shenyu.register.registerType=http",
+ "shenyu.register.serverLists=http://localhost:9095",
+ "shenyu.register.props.username=admin",
+ "shenyu.register.props.password=123456",
+ "shenyu.client.brpc.props[contextPath]=/brpc",
+ "shenyu.client.brpc.props[ipAndPort]=127.0.0.1:21715",
+ "shenyu.client.brpc.props[host]=127.0.0.1",
+ "shenyu.client.brpc.props[port]=21715"
+ );
+ }
+
+ @Test
+ public void testBrpcContextRefreshedEventListener() {
+ MockedStatic<RegisterUtils> registerUtilsMockedStatic = mockStatic(RegisterUtils.class);
+ registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.ofNullable("token"));
+ applicationContextRunner.run(context -> {
+ BrpcContextRefreshedEventListener listener = context.getBean("brpcContextRefreshedEventListener", BrpcContextRefreshedEventListener.class);
+ assertNotNull(listener);
+ });
+ registerUtilsMockedStatic.close();
+ }
+}