Merge remote-tracking branch 'origin/develop' into new_feature

pull/649/head
pizihao 3 years ago
commit 174c18c3c8

@ -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) 任务列表。
<a href="https://github.com/opengoofy/hippo4j/graphs/contributors"><img src="https://opencollective.com/hippo4j/contributors.svg?width=890&button=false" /></a>

@ -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/)

@ -64,7 +64,7 @@ const config = {
// content: `<a target="_blank" rel="noopener noreferrer" href="https://xiaomage.info/knowledge-planet/">👉 《小马哥的代码实战课》官方知识星球来啦!!!</a>`,
},
navbar: {
title: 'hippoforjava',
title: 'HIPPO-4J',
logo: {
alt: 'HIPPO-4J 动态可观测线程池框架',
src: 'img/web.png',

@ -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();
}

@ -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<String> 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);
}
}

@ -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);
}
}

@ -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));
}
}

@ -56,6 +56,14 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.etcd</groupId>
<artifactId>jetcd-core</artifactId>
<version>${jetcd.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>

@ -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<String, String> zookeeper;
/**
* etcd config
*/
private Map<String, String> etcd;
/**
* Tomcat thread pool config.
*/

@ -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();
}
}
}

@ -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<String, String> 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;
}
}

@ -49,6 +49,7 @@
<mybatis-plus.version>3.4.2</mybatis-plus.version>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<apollo.version>1.9.1</apollo.version>
<jetcd.version>0.7.3</jetcd.version>
<rocketmq.version>2.2.2</rocketmq.version>
<netty.version>4.1.56.Final</netty.version>
<tomcat-embed-core.version>9.0.55</tomcat-embed-core.version>

Loading…
Cancel
Save