From eb1f0b250c20045bb665826cdd341343007d90f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BA=8C=E5=B8=88=E5=85=84?=
<102774648+gywanghai@users.noreply.github.com>
Date: Wed, 31 Aug 2022 08:16:55 +0800
Subject: [PATCH 1/6] Update README.md (#615)
Update README.md: update the second "[good first issue]" to "[good pro issue]"
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 80a6bb4a..4319d233 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,7 @@ Hippo-4J 获得了一些宝贵的荣誉,肯定了 Hippo-4J 作为一款开源
Hippo-4J 获得的成就属于每一位对 Hippo-4J 做出过贡献的成员,感谢各位的贡献。
-如果屏幕前的同学有意提交 Hippo-4J,请参考 [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) 或者 [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+pro+issue%22) 任务列表。
+如果屏幕前的同学有意提交 Hippo-4J,请参考 [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) 或者 [good pro issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+pro+issue%22) 任务列表。
From da9e48785df21d79f1240ecdc5ede6bcc3f294f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?bug=E6=90=AC=E8=BF=90=E5=B7=A5?= <15618796966@163.com>
Date: Wed, 31 Aug 2022 09:37:18 +0800
Subject: [PATCH 2/6] test: add ut (#616)
---
.../hippo4j/common/toolkit/ArrayUtilTest.java | 25 +++++++-
.../common/toolkit/CalculateUtilTest.java | 4 +-
.../common/toolkit/CollectionUtilTest.java | 59 +++++++++++++++++++
3 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/ArrayUtilTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/ArrayUtilTest.java
index c237c461..358dfd9f 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/ArrayUtilTest.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/ArrayUtilTest.java
@@ -17,8 +17,13 @@
package cn.hippo4j.common.toolkit;
+import cn.hippo4j.common.function.Matcher;
+import com.google.common.base.Strings;
+import org.checkerframework.checker.units.qual.A;
import org.junit.Test;
+import java.lang.reflect.Array;
+
public class ArrayUtilTest {
@Test
@@ -29,21 +34,39 @@ public class ArrayUtilTest {
@Test
public void assertIsNotEmpty() {
-
+ String[] array = new String[0];
+ Assert.isTrue(!ArrayUtil.isNotEmpty(array));
}
@Test
public void assertFirstMatch() {
+ Matcher matcher = (str) -> "1".equalsIgnoreCase(str);
+ String[] array = new String[0];
+ Assert.isTrue(Strings.isNullOrEmpty(ArrayUtil.firstMatch(matcher, array)));
+
+ array = new String[]{"0"};
+ Assert.isTrue(Strings.isNullOrEmpty(ArrayUtil.firstMatch(matcher, array)));
+
+ array = new String[]{"1"};
+ Assert.isTrue(!Strings.isNullOrEmpty(ArrayUtil.firstMatch(matcher, array)));
}
@Test
public void assertAddAll() {
+ String[] array = new String[]{"1"};
+ Assert.isTrue(ArrayUtil.addAll(array, null).length == 1);
+ Assert.isTrue(ArrayUtil.addAll(null, array).length == 1);
+ Assert.isTrue(ArrayUtil.addAll(array, new String[]{"1"}).length == 2);
}
@Test
public void assertClone() {
+ Assert.isNull(ArrayUtil.clone(null));
+ String[] array = new String[0];
+ Assert.isTrue(array != ArrayUtil.clone(array));
+ Assert.isTrue(array.length == ArrayUtil.clone(array).length);
}
}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CalculateUtilTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CalculateUtilTest.java
index 55ca885b..715c71c6 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CalculateUtilTest.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CalculateUtilTest.java
@@ -23,6 +23,8 @@ public class CalculateUtilTest {
@Test
public void assertDivide() {
-
+ Assert.isTrue(CalculateUtil.divide(200, 100) == 200);
+ Assert.isTrue(CalculateUtil.divide(100, 200) == 50);
+ Assert.isTrue(CalculateUtil.divide(100, 100) == 100);
}
}
diff --git a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CollectionUtilTest.java b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CollectionUtilTest.java
index f2e47338..b0be6add 100644
--- a/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CollectionUtilTest.java
+++ b/hippo4j-common/src/test/java/cn/hippo4j/common/toolkit/CollectionUtilTest.java
@@ -17,22 +17,81 @@
package cn.hippo4j.common.toolkit;
+import com.google.common.collect.Maps;
+import org.assertj.core.util.Lists;
import org.junit.Test;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
public class CollectionUtilTest {
@Test
public void assertGetFirst() {
+ Assert.isNull(CollectionUtil.getFirst(null));
+ String first = CollectionUtil.getFirst(Lists.newArrayList("1", "2"));
+ Assert.notEmpty(first);
}
@Test
public void assertIsEmpty() {
+ List list = null;
+ Assert.isTrue(CollectionUtil.isEmpty(list));
+
+ list = Lists.newArrayList();
+ Assert.isTrue(CollectionUtil.isEmpty(list));
+
+ list = Lists.newArrayList("1");
+ Assert.isTrue(!CollectionUtil.isEmpty(list));
+
+ Map map = null;
+ Assert.isTrue(CollectionUtil.isEmpty(map));
+
+ map = Maps.newHashMap();
+ Assert.isTrue(CollectionUtil.isEmpty(map));
+
+ map.put("key", "value");
+ Assert.isTrue(!CollectionUtil.isEmpty(map));
+
+ Iterator iterator = null;
+ Assert.isTrue(CollectionUtil.isEmpty(iterator));
+
+ iterator = Lists.emptyList().iterator();
+ Assert.isTrue(CollectionUtil.isEmpty(iterator));
+ iterator = Lists.newArrayList("1").iterator();
+ Assert.isTrue(!CollectionUtil.isEmpty(iterator));
}
@Test
public void assertIsNotEmpty() {
+ List list = null;
+ Assert.isTrue(!CollectionUtil.isNotEmpty(list));
+
+ list = Lists.newArrayList();
+ Assert.isTrue(!CollectionUtil.isNotEmpty(list));
+
+ list = Lists.newArrayList("1");
+ Assert.isTrue(CollectionUtil.isNotEmpty(list));
+
+ Map map = null;
+ Assert.isTrue(!CollectionUtil.isNotEmpty(map));
+
+ map = Maps.newHashMap();
+ Assert.isTrue(!CollectionUtil.isNotEmpty(map));
+
+ map.put("key", "value");
+ Assert.isTrue(CollectionUtil.isNotEmpty(map));
+
+ Iterator iterator = null;
+ Assert.isTrue(!CollectionUtil.isNotEmpty(iterator));
+
+ iterator = Lists.emptyList().iterator();
+ Assert.isTrue(!CollectionUtil.isNotEmpty(iterator));
+ iterator = Lists.newArrayList("1").iterator();
+ Assert.isTrue(CollectionUtil.isNotEmpty(iterator));
}
}
From a655b1dad47441c5e6caefb1d9b91509c1b24a3b Mon Sep 17 00:00:00 2001
From: lucky 8 <40255310+shining-stars-lk@users.noreply.github.com>
Date: Wed, 31 Aug 2022 11:24:39 +0800
Subject: [PATCH 3/6] Fix the UndertowWeb adaptation (#619)
* Fix the UndertowWeb adaptation
* Fix the UndertowWeb adaptation
---
.../adapter/web/UndertowWebThreadPoolHandler.java | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java
index bfdc5b7d..90ba9b7f 100644
--- a/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java
+++ b/hippo4j-adapter/hippo4j-adapter-web/src/main/java/cn/hippo4j/adapter/web/UndertowWebThreadPoolHandler.java
@@ -27,7 +27,7 @@ import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
import cn.hutool.core.date.DateUtil;
import io.undertow.Undertow;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.web.embedded.undertow.UndertowWebServer;
+import org.springframework.boot.web.embedded.undertow.UndertowServletWebServer;
import org.springframework.boot.web.server.WebServer;
import org.springframework.util.ReflectionUtils;
import org.xnio.Options;
@@ -50,11 +50,12 @@ public class UndertowWebThreadPoolHandler extends AbstractWebThreadPoolService {
@Override
protected Executor getWebThreadPoolByServer(WebServer webServer) {
// There is no need to consider reflection performance because the fetch is a singleton.
- UndertowWebServer undertowWebServer = (UndertowWebServer) webServer;
- Field undertowField = ReflectionUtils.findField(UndertowWebServer.class, UNDERTOW_NAME);
+ // Springboot 2-3 version, can directly through reflection to obtain the undertow property
+ UndertowServletWebServer undertowServletWebServer = (UndertowServletWebServer) webServer;
+ Field undertowField = ReflectionUtils.findField(UndertowServletWebServer.class, UNDERTOW_NAME);
ReflectionUtils.makeAccessible(undertowField);
- Undertow undertow = (Undertow) ReflectionUtils.getField(undertowField, undertowWebServer);
+ Undertow undertow = (Undertow) ReflectionUtils.getField(undertowField, undertowServletWebServer);
return Objects.isNull(undertow) ? null : undertow.getWorker();
}
From 2813f7260c59ad97a1f29107a6e2a52d9324bdef Mon Sep 17 00:00:00 2001
From: weihubeats
Date: Wed, 31 Aug 2022 11:28:42 +0800
Subject: [PATCH 4/6] add etcd (#618)
---
.../pom.xml | 8 ++
.../config/BootstrapConfigProperties.java | 12 +-
.../config/ConfigHandlerConfiguration.java | 16 +++
.../refresher/EtcdRefresherHandler.java | 105 ++++++++++++++++++
pom.xml | 1 +
5 files changed, 139 insertions(+), 3 deletions(-)
create mode 100644 hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/refresher/EtcdRefresherHandler.java
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml
index d3ba03c1..9c3ed8e7 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/pom.xml
@@ -56,6 +56,14 @@
true
+
+ io.etcd
+ jetcd-core
+ ${jetcd.version}
+ compile
+ true
+
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/BootstrapConfigProperties.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/BootstrapConfigProperties.java
index 430786b1..62ec0ffe 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/BootstrapConfigProperties.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/BootstrapConfigProperties.java
@@ -17,14 +17,15 @@
package cn.hippo4j.core.springboot.starter.config;
+import java.util.List;
+import java.util.Map;
+
import cn.hippo4j.core.config.BootstrapPropertiesInterface;
import cn.hippo4j.core.springboot.starter.parser.ConfigFileTypeEnum;
import lombok.Getter;
import lombok.Setter;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import java.util.List;
-import java.util.Map;
+import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Bootstrap core properties.
@@ -86,6 +87,11 @@ public class BootstrapConfigProperties implements BootstrapPropertiesInterface {
*/
private Map zookeeper;
+ /**
+ * etcd config
+ */
+ private Map etcd;
+
/**
* Tomcat thread pool config.
*/
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/ConfigHandlerConfiguration.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/ConfigHandlerConfiguration.java
index 23bca9d3..493d2f1d 100644
--- a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/ConfigHandlerConfiguration.java
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/ConfigHandlerConfiguration.java
@@ -21,8 +21,10 @@ import cn.hippo4j.core.springboot.starter.refresher.ApolloRefresherHandler;
import cn.hippo4j.core.springboot.starter.refresher.NacosCloudRefresherHandler;
import cn.hippo4j.core.springboot.starter.refresher.NacosRefresherHandler;
import cn.hippo4j.core.springboot.starter.refresher.ZookeeperRefresherHandler;
+import cn.hippo4j.core.springboot.starter.refresher.EtcdRefresherHandler;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.ConfigService;
+import io.etcd.jetcd.Client;
import lombok.RequiredArgsConstructor;
import org.apache.curator.framework.CuratorFramework;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -45,6 +47,8 @@ public class ConfigHandlerConfiguration {
private static final String ZOOKEEPER_CONNECT_STR_KEY = "zookeeper.zk-connect-str";
+ private static final String ETCD = "endpoints";
+
@RequiredArgsConstructor
@ConditionalOnClass(ConfigService.class)
@ConditionalOnMissingClass(NACOS_CONFIG_MANAGER_KEY)
@@ -88,4 +92,16 @@ public class ConfigHandlerConfiguration {
return new ZookeeperRefresherHandler();
}
}
+
+ @ConditionalOnClass(Client.class)
+ @ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, name = ETCD)
+ static class EmbeddedEtcd {
+
+ @Bean
+ public EtcdRefresherHandler etcdRefresher() {
+ return new EtcdRefresherHandler();
+ }
+ }
+
+
}
diff --git a/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/refresher/EtcdRefresherHandler.java b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/refresher/EtcdRefresherHandler.java
new file mode 100644
index 00000000..0754752b
--- /dev/null
+++ b/hippo4j-spring-boot/hippo4j-config-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/refresher/EtcdRefresherHandler.java
@@ -0,0 +1,105 @@
+package cn.hippo4j.core.springboot.starter.refresher;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Objects;
+
+import cn.hippo4j.common.toolkit.JSONUtil;
+import cn.hippo4j.common.toolkit.StringUtil;
+import io.etcd.jetcd.ByteSequence;
+import io.etcd.jetcd.Client;
+import io.etcd.jetcd.ClientBuilder;
+import io.etcd.jetcd.KeyValue;
+import io.etcd.jetcd.Watch;
+import io.etcd.jetcd.watch.WatchEvent;
+import io.etcd.jetcd.watch.WatchResponse;
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ *@author : wh
+ *@date : 2022/8/30 17:59
+ *@description:
+ */
+@Slf4j
+public class EtcdRefresherHandler extends AbstractCoreThreadPoolDynamicRefresh implements ApplicationContextAware {
+
+ private ApplicationContext applicationContext;
+
+ private Client client;
+
+ private static final String ENDPOINTS = "endpoints";
+
+ private static final String USER = "user";
+
+ private static final String PASSWORD = "password";
+
+ private static final String CHARSET = "charset";
+
+ private static final String AUTHORITY = "authority";
+
+ private static final String KEY = "key";
+
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ Map etcd = bootstrapConfigProperties.getEtcd();
+ String user = etcd.get(USER);
+ String password = etcd.get(PASSWORD);
+ String endpoints = etcd.get(ENDPOINTS);
+ String authority = etcd.get(AUTHORITY);
+ String key = etcd.get(KEY);
+ Charset charset = StringUtil.isBlank(etcd.get(CHARSET)) ? StandardCharsets.UTF_8 : Charset.forName(etcd.get(CHARSET));
+
+ ClientBuilder clientBuilder = Client.builder().endpoints(endpoints.split(","));
+
+ client = applicationContext.getBean(Client.class);
+ if (Objects.isNull(client)) {
+ client = StringUtil.isAllNotEmpty(user, password) ? clientBuilder.user(ByteSequence.from(user, charset))
+ .password(ByteSequence.from(password, charset)).authority(authority)
+ .build() : clientBuilder.build();
+ }
+
+ // todo Currently only supports json
+ KeyValue keyValue = client.getKVClient().get(ByteSequence.from(key, charset)).get().getKvs().get(0);
+ if (Objects.isNull(keyValue)) {
+ return;
+ }
+
+ client.getWatchClient().watch(ByteSequence.from(key, charset), new Watch.Listener() {
+ @Override
+ public void onNext(WatchResponse response) {
+ WatchEvent watchEvent = response.getEvents().get(0);
+ WatchEvent.EventType eventType = watchEvent.getEventType();
+ // todo Currently only supports json
+ if (Objects.equals(eventType, WatchEvent.EventType.PUT)) {
+ KeyValue keyValue1 = watchEvent.getKeyValue();
+ String value = keyValue1.getValue().toString(charset);
+ Map map = JSONUtil.parseObject(value, Map.class);
+ dynamicRefresh(keyValue1.getKey().toString(charset), map);
+ }
+
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ log.error("dynamic thread pool etcd config watcher exception ", throwable);
+ }
+
+ @Override
+ public void onCompleted() {
+ log.info("dynamic thread pool etcd config key refreshed, config key {}", key);
+ }
+ });
+
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+}
diff --git a/pom.xml b/pom.xml
index ec01bb02..ca39d771 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,7 @@
3.4.2
2.3.2.RELEASE
1.9.1
+ 0.7.3
2.2.2
4.1.56.Final
9.0.55
From f3c5fc083bbb534c2d535a7f9c67daa50a14a3ea Mon Sep 17 00:00:00 2001
From: Lijx
Date: Wed, 31 Aug 2022 18:18:51 +0800
Subject: [PATCH 5/6] Register company information (#621)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 登记公司
* Register company information
---
docs/docs/community/powered-by.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/docs/docs/community/powered-by.md b/docs/docs/community/powered-by.md
index ced23458..4570ffa3 100644
--- a/docs/docs/community/powered-by.md
+++ b/docs/docs/community/powered-by.md
@@ -12,7 +12,7 @@ sidebar_position: 3
## 谁在使用 Hippo4J
-共计 16+ 家公司生产接入 Hippo4J。按照公司登记时间排序。
+共计 17+ 家公司生产接入 Hippo4J。按照公司登记时间排序。
- [身边云](https://serviceshare.com)
- [Medbanks](https://www.medbanks.cn)
@@ -30,3 +30,4 @@ sidebar_position: 3
- [众合云科(51社保)](https://home.101hr.com/)
- [好货云店](https://pc.haohuoyundian.com/)
- [斗象科技](https://www.tophant.com/)
+- [深圳航天信息有限公司](http://sz.aisino.com/)
From 6a0a05728907bbcf8976c85679347f5476543190 Mon Sep 17 00:00:00 2001
From: "chen.ma"
Date: Wed, 31 Aug 2022 22:10:08 +0800
Subject: [PATCH 6/6] Update official documentation
---
docs/docusaurus.config.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index d5d60cd7..50df8518 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -64,7 +64,7 @@ const config = {
// content: `👉 《小马哥的代码实战课》官方知识星球来啦!!!`,
},
navbar: {
- title: 'hippoforjava',
+ title: 'HIPPO-4J',
logo: {
alt: 'HIPPO-4J 动态可观测线程池框架',
src: 'img/web.png',