feat: support spring boot 1.5.x (#796)

* feat: support spring boot 1.5.x

* fix: fix ^M

* fix: fix ^M

* feat: close debug

* fix: update properties

* feat: add apollo spring-boot 1.5.x example
pull/805/head
BigXin0109 2 years ago committed by GitHub
parent 16fefd9fc6
commit 07bb0528df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,6 +33,15 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public class WebIpAndPortHolder {
private static boolean support = false;
static {
try {
Class.forName("org.springframework.boot.web.server.WebServer");
support = true;
} catch (Exception e) {
}
}
/**
* Application ip and application post
*/
@ -47,6 +56,9 @@ public class WebIpAndPortHolder {
}
protected static void initIpAndPort() {
if (!support) {
return;
}
webIpAndPort.compareAndSet(null, getWebIpAndPortInfo());
}
@ -83,7 +95,7 @@ public class WebIpAndPortHolder {
*/
public static boolean check(String nodes) {
WebIpAndPortInfo webIpAndPort = WebIpAndPortHolder.getWebIpAndPort();
if (StringUtil.isEmpty(nodes) || ALL.equals(nodes)) {
if (StringUtil.isEmpty(nodes) || ALL.equals(nodes) || webIpAndPort == null) {
return true;
}
String[] splitNodes = nodes.split(SEPARATOR);

@ -49,10 +49,7 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example</artifactId>
<version>${revision}</version>
</parent>
<artifactId>hippo4j-config-apollo-spring-boot-1.5-starter-example</artifactId>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
<spring-boot.version>1.5.22.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example-core</artifactId>
<version>${revision}</version>
</dependency>
<!-- <dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-config-spring-boot-starter</artifactId>
<version>${revision}</version>
</dependency>
-->
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-config-spring-boot-1.5-starter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>${apollo.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>1.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-spring-legacy</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,31 @@
/*
* 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 cn.hippo4j.example.config.apollo;
import cn.hippo4j.core.enable.EnableDynamicThreadPool;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableDynamicThreadPool
@SpringBootApplication(scanBasePackages = "cn.hippo4j.example.core")
public class ConfigApolloSpringBoot15ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApolloSpringBoot15ExampleApplication.class, args);
}
}

@ -0,0 +1,63 @@
# Configuration reference: https://hippo4j.cn/pages/2f674h
server.port=8091
server.servlet.context-path=/example
app.id=dynamic-threadpool-example
apollo.meta=http://127.0.0.1:8080
apollo.autoUpdateInjectedSpringProperties=true
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=application
apollo.bootstrap.eagerLoad.enabled=true
spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example
management.metrics.export.prometheus.enabled=true
management.server.port=29998
management.endpoints.web.exposure.include=*
spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=true
spring.dynamic.thread-pool.check-state-interval=3
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ac0426a5-c712-474c-9bff-72b8b8f5caff
spring.dynamic.thread-pool.notify-platforms[1].platform=DING
spring.dynamic.thread-pool.notify-platforms[1].secret-key=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
spring.dynamic.thread-pool.notify-platforms[2].secret-key=2cbf2808-3839-4c26-a04d-fd201dd51f9e
spring.dynamic.thread-pool.apollo.namespace=application
spring.dynamic.thread-pool.config-file-type=properties
spring.dynamic.thread-pool.executors[0].active-alarm = 80
spring.dynamic.thread-pool.executors[0].alarm = true
spring.dynamic.thread-pool.executors[0].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[0].blocking-queue = LinkedBlockingQueue
spring.dynamic.thread-pool.executors[0].capacity-alarm = 80
spring.dynamic.thread-pool.executors[0].core-pool-size = 1
spring.dynamic.thread-pool.executors[0].execute-time-out = 1000
spring.dynamic.thread-pool.executors[0].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[0].maximum-pool-size = 1
spring.dynamic.thread-pool.executors[0].notify.interval = 8
spring.dynamic.thread-pool.executors[0].notify.receives = chen.ma
spring.dynamic.thread-pool.executors[0].queue-capacity = 1
spring.dynamic.thread-pool.executors[0].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[0].thread-name-prefix = message-consume
spring.dynamic.thread-pool.executors[0].thread-pool-id = message-consume
spring.dynamic.thread-pool.executors[1].active-alarm = 80
spring.dynamic.thread-pool.executors[1].alarm = true
spring.dynamic.thread-pool.executors[1].allow-core-thread-time-out = true
spring.dynamic.thread-pool.executors[1].blocking-queue = LinkedBlockingQueue
spring.dynamic.thread-pool.executors[1].capacity-alarm = 80
spring.dynamic.thread-pool.executors[1].core-pool-size = 1
spring.dynamic.thread-pool.executors[1].execute-time-out = 1000
spring.dynamic.thread-pool.executors[1].keep-alive-time = 6691
spring.dynamic.thread-pool.executors[1].maximum-pool-size = 1
spring.dynamic.thread-pool.executors[1].notify.interval = 8
spring.dynamic.thread-pool.executors[1].notify.receives = chen.ma
spring.dynamic.thread-pool.executors[1].queue-capacity = 1
spring.dynamic.thread-pool.executors[1].rejected-handler = AbortPolicy
spring.dynamic.thread-pool.executors[1].thread-name-prefix = message-produce
spring.dynamic.thread-pool.executors[1].thread-pool-id = message-produce

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example</artifactId>
<version>${revision}</version>
</parent>
<artifactId>hippo4j-config-nacos-spring-boot-1.5-starter-example</artifactId>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
<spring-boot.version>1.5.22.RELEASE</spring-boot.version>
<nacos-client.version>1.1.4</nacos-client.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-example-core</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-config-spring-boot-1.5-starter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-spring-legacy</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,31 @@
/*
* 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 cn.hippo4j.example.config.nacos;
import cn.hippo4j.core.enable.EnableDynamicThreadPool;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableDynamicThreadPool
@SpringBootApplication(scanBasePackages = "cn.hippo4j.example.core")
public class ConfigNacosSpringBoot15ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigNacosSpringBoot15ExampleApplication.class, args);
}
}

@ -0,0 +1,32 @@
#debug=true
server.port=8089
server.servlet.context-path=/example
management.metrics.export.prometheus.enabled=true
management.server.port=29999
management.endpoints.web.exposure.include=*
spring.profiles.active=dev
spring.application.name=dynamic-threadpool-example
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.ext-config[0].data-id=hippo4j-nacos.yaml
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.dynamic.thread-pool.enable=true
spring.dynamic.thread-pool.banner=true
spring.dynamic.thread-pool.collect=true
spring.dynamic.thread-pool.collect-type=micrometer
spring.dynamic.thread-pool.check-state-interval=5
spring.dynamic.thread-pool.notify-platforms[0].platform=WECHAT
spring.dynamic.thread-pool.notify-platforms[0].secret-key=ac0426a5-c712-474c-9bff-72b8b8f5caff
spring.dynamic.thread-pool.notify-platforms[1].platform=DING
spring.dynamic.thread-pool.notify-platforms[1].secret-key=56417ebba6a27ca352f0de77a2ae9da66d01f39610b5ee8a6033c60ef9071c55
spring.dynamic.thread-pool.notify-platforms[2].platform=LARK
spring.dynamic.thread-pool.notify-platforms[2].secret-key=2cbf2808-3839-4c26-a04d-fd201dd51f9e
spring.dynamic.thread-pool.nacos.data-id=hippo4j-nacos.yaml
spring.dynamic.thread-pool.nacos.group=DEFAULT_GROUP
spring.dynamic.thread-pool.config-file-type=yml

@ -23,6 +23,8 @@
<module>hippo4j-spring-boot-starter-adapter-spring-cloud-stream-rocketmq-example</module>
<module>hippo4j-spring-boot-starter-adapter-rocketmq-example</module>
<module>hippo4j-config-etcd-spring-boot-starter-example</module>
<module>hippo4j-config-nacos-spring-boot-1.5-starter-example</module>
<module>hippo4j-config-apollo-spring-boot-1.5-starter-example</module>
</modules>
<properties>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>cn.hippo4j</groupId>
<artifactId>hippo4j-spring-boot</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hippo4j-config-spring-boot-1.5-starter</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring-boot.version>1.5.22.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-config-spring-boot-starter</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,36 @@
/*
* 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 cn.hippo4j.config.springboot15x.starter.config;
import cn.hippo4j.config.springboot.starter.refresher.BootstrapConfigPropertiesBinderAdapt;
import cn.hippo4j.config.springboot15x.starter.refresher.SpringBoot15BootstrapConfigPropertiesBinderAdapt;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConfigHandlerConfiguration {
@Bean
@ConditionalOnClass(RelaxedDataBinder.class)
public BootstrapConfigPropertiesBinderAdapt bootstrapConfigPropertiesBinderAdapt() {
return new SpringBoot15BootstrapConfigPropertiesBinderAdapt();
}
}

@ -0,0 +1,109 @@
/*
* 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 cn.hippo4j.config.springboot15x.starter.refresher;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import cn.hippo4j.config.springboot.starter.refresher.BootstrapConfigPropertiesBinderAdapt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.support.ResourceEditorRegistrar;
import org.springframework.boot.bind.CustomPropertyNamePatternsMatcher;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.bind.RelaxedNames;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Bootstrap core properties binder adapt.
*/
public class SpringBoot15BootstrapConfigPropertiesBinderAdapt implements ApplicationContextAware, BootstrapConfigPropertiesBinderAdapt {
private ApplicationContext applicationContext;
/**
* Bootstrap core properties binder.
*
* @param configInfo
* @param bootstrapConfigProperties
* @return
*/
@Override
public BootstrapConfigProperties bootstrapCorePropertiesBinder(Map<Object, Object> configInfo, BootstrapConfigProperties bootstrapConfigProperties) {
BootstrapConfigProperties bindableCoreProperties = new BootstrapConfigProperties();
RelaxedNames relaxedNames = new RelaxedNames(BootstrapConfigProperties.PREFIX);
Set<String> names = getNames(bindableCoreProperties, relaxedNames);
// 绑定器
Map<String, Object> stringConfigInfo = new HashMap<>(configInfo.size());
configInfo.forEach((key, value) -> stringConfigInfo.put(key.toString(), value));
MapPropertySource test = new MapPropertySource("Hippo4j", stringConfigInfo);
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addFirst(test);
PropertyValues propertyValues = CustomPropertyNamePatternsMatcher.getPropertySourcesPropertyValues(names, propertySources);
RelaxedDataBinder dataBinder = new RelaxedDataBinder(bindableCoreProperties, BootstrapConfigProperties.PREFIX);
dataBinder.setAutoGrowCollectionLimit(Integer.MAX_VALUE);
dataBinder.setIgnoreNestedProperties(false);
dataBinder.setIgnoreInvalidFields(false);
dataBinder.setIgnoreUnknownFields(true);
ResourceEditorRegistrar resourceEditorRegistrar = new ResourceEditorRegistrar(applicationContext, applicationContext.getEnvironment());
resourceEditorRegistrar.registerCustomEditors(dataBinder);
dataBinder.bind(propertyValues);
return bindableCoreProperties;
}
private static Set<String> getNames(Object target, Iterable<String> prefixes) {
Set<String> names = new LinkedHashSet<>();
if (target != null) {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(target.getClass());
for (PropertyDescriptor descriptor : descriptors) {
String name = descriptor.getName();
if (!"class".equals(name)) {
RelaxedNames relaxedNames = RelaxedNames.forCamelCase(name);
if (prefixes == null) {
for (String relaxedName : relaxedNames) {
names.add(relaxedName);
}
} else {
for (String prefix : prefixes) {
for (String relaxedName : relaxedNames) {
names.add(prefix + "." + relaxedName);
names.add(prefix + "_" + relaxedName);
}
}
}
}
}
}
return names;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

@ -0,0 +1,41 @@
/*
* 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.springframework.boot.bind;
import org.springframework.beans.PropertyValues;
import org.springframework.boot.bind.DefaultPropertyNamePatternsMatcher;
import org.springframework.boot.bind.PropertyNamePatternsMatcher;
import org.springframework.boot.bind.PropertySourcesPropertyValues;
import org.springframework.core.env.MutablePropertySources;
import java.util.Set;
public class CustomPropertyNamePatternsMatcher {
private static final char[] EXACT_DELIMITERS = {'_', '.', '['};
public static PropertyValues getPropertySourcesPropertyValues(Set<String> names, MutablePropertySources propertySources) {
PropertyNamePatternsMatcher includes = getPropertyNamePatternsMatcher(names);
return new PropertySourcesPropertyValues(propertySources, names, includes, true);
}
private static PropertyNamePatternsMatcher getPropertyNamePatternsMatcher(Set<String> names) {
return new DefaultPropertyNamePatternsMatcher(EXACT_DELIMITERS, true, names);
}
}

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.hippo4j.config.springboot15x.starter.config.ConfigHandlerConfiguration

@ -19,6 +19,7 @@ package cn.hippo4j.config.springboot.starter.config;
import cn.hippo4j.config.springboot.starter.refresher.*;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.config.ConfigService;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import io.etcd.jetcd.Client;
@ -26,6 +27,7 @@ import lombok.RequiredArgsConstructor;
import org.apache.curator.framework.CuratorFramework;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
@ -49,17 +51,21 @@ public class ConfigHandlerConfiguration {
private static final String POLARIS = "config.serverConnector";
@Bean
@ConditionalOnMissingBean
public BootstrapConfigPropertiesBinderAdapt bootstrapConfigPropertiesBinderAdapt() {
return new DefaultBootstrapConfigPropertiesBinderAdapt();
}
@RequiredArgsConstructor
@ConditionalOnClass(ConfigService.class)
@ConditionalOnMissingClass(NACOS_CONFIG_MANAGER_KEY)
@ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, name = NACOS_DATA_ID_KEY)
static class EmbeddedNacos {
public final BootstrapConfigProperties bootstrapConfigProperties;
@Bean
public NacosRefresherHandler nacosRefresherHandler() {
return new NacosRefresherHandler(bootstrapConfigProperties);
public NacosRefresherHandler nacosRefresherHandler(NacosConfigProperties nacosConfigProperties) {
return new NacosRefresherHandler(nacosConfigProperties);
}
}

@ -59,11 +59,7 @@ import org.springframework.core.annotation.Order;
@ConditionalOnBean(MarkerConfiguration.Marker.class)
@EnableConfigurationProperties(BootstrapConfigProperties.class)
@ConditionalOnProperty(prefix = BootstrapConfigProperties.PREFIX, value = "enable", matchIfMissing = true, havingValue = "true")
@Import({
ConfigHandlerConfiguration.EmbeddedNacos.class, ConfigHandlerConfiguration.EmbeddedNacosCloud.class,
ConfigHandlerConfiguration.EmbeddedApollo.class, ConfigHandlerConfiguration.EmbeddedZookeeper.class,
ConfigHandlerConfiguration.EmbeddedEtcd.class
})
@Import({ConfigHandlerConfiguration.class})
@ImportAutoConfiguration({WebAdapterConfiguration.class, UtilAutoConfiguration.class, MessageConfiguration.class, LocalLogMonitorConfiguration.class, MicrometerMonitorConfiguration.class})
public class DynamicThreadPoolAutoConfiguration {

@ -37,19 +37,21 @@ import java.util.concurrent.ExecutorService;
* Abstract core thread-pool dynamic refresh.
*/
@Slf4j
@RequiredArgsConstructor
public abstract class AbstractConfigThreadPoolDynamicRefresh
implements
ThreadPoolDynamicRefresh,
ThreadPoolInitRefresh,
InitializingBean {
protected final BootstrapConfigProperties bootstrapConfigProperties;
private final BootstrapConfigPropertiesBinderAdapt bootstrapConfigPropertiesBinderAdapt;
protected BootstrapConfigProperties bootstrapConfigProperties;
protected final ExecutorService dynamicRefreshExecutorService = ThreadPoolBuilder.builder().singlePool("client.dynamic.refresh").build();
public AbstractConfigThreadPoolDynamicRefresh() {
bootstrapConfigProperties = ApplicationContextHolder.getBean(BootstrapConfigProperties.class);
bootstrapConfigPropertiesBinderAdapt = ApplicationContextHolder.getBean(BootstrapConfigPropertiesBinderAdapt.class);
}
@Override
@ -69,7 +71,7 @@ public abstract class AbstractConfigThreadPoolDynamicRefresh
if (CollectionUtil.isNotEmpty(newValueChangeMap)) {
Optional.ofNullable(configInfo).ifPresent(each -> each.putAll(newValueChangeMap));
}
BootstrapConfigProperties bindableCoreProperties = BootstrapConfigPropertiesBinderAdapt.bootstrapCorePropertiesBinder(configInfo, bootstrapConfigProperties);
BootstrapConfigProperties bindableCoreProperties = bootstrapConfigPropertiesBinderAdapt.bootstrapCorePropertiesBinder(configInfo, bootstrapConfigProperties);
ApplicationContextHolder.getInstance().publishEvent(new Hippo4jConfigDynamicRefreshEvent(this, bindableCoreProperties));
} catch (Exception ex) {
log.error("Hippo-4J core dynamic refresh failed.", ex);

@ -17,142 +17,11 @@
package cn.hippo4j.config.springboot.starter.refresher;
import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import cn.hippo4j.config.springboot.starter.config.DynamicThreadPoolNotifyProperties;
import cn.hippo4j.config.springboot.starter.config.ExecutorProperties;
import cn.hippo4j.config.springboot.starter.config.NotifyPlatformProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Bootstrap core properties binder adapt.
*/
public class BootstrapConfigPropertiesBinderAdapt {
/**
* Bootstrap core properties binder.
*
* @param configInfo
* @param bootstrapConfigProperties
* @return
*/
public static BootstrapConfigProperties bootstrapCorePropertiesBinder(Map<Object, Object> configInfo, BootstrapConfigProperties bootstrapConfigProperties) {
BootstrapConfigProperties bindableCoreProperties = null;
try {
ConfigurationPropertySource sources = new MapConfigurationPropertySource(configInfo);
Binder binder = new Binder(sources);
bindableCoreProperties = binder.bind(BootstrapConfigProperties.PREFIX, Bindable.ofInstance(bootstrapConfigProperties)).get();
} catch (Exception ex) {
try {
Class.forName("org.springframework.boot.context.properties.bind.Binder");
} catch (ClassNotFoundException notEx) {
bindableCoreProperties = adapt(configInfo);
}
}
return bindableCoreProperties;
}
/**
* SpringBoot 1.5.x, , PR.
*
* @param configInfo
* @return
*/
@Deprecated
private static BootstrapConfigProperties adapt(Map<Object, Object> configInfo) {
BootstrapConfigProperties bindableConfigProperties;
try {
// filter
Map<Object, Object> targetMap = new HashMap<>();
configInfo.forEach((key, val) -> {
boolean containFlag = key != null
&& StringUtil.isNotBlank((String) key)
&& (((String) key).indexOf(BootstrapConfigProperties.PREFIX + ".executors") != -1
|| ((String) key).indexOf(BootstrapConfigProperties.PREFIX + ".notify-platforms") != -1
|| ((String) key).indexOf(BootstrapConfigProperties.PREFIX + ".notifyPlatforms") != -1);
if (containFlag) {
String targetKey = key.toString().replace(BootstrapConfigProperties.PREFIX + ".", "");
targetMap.put(targetKey, val);
}
});
// convert
List<ExecutorProperties> executorPropertiesList = new ArrayList<>();
List<NotifyPlatformProperties> notifyPropertiesList = new ArrayList<>();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
Map<String, Object> executorSingleMap = new HashMap<>();
Map<String, Object> platformSingleMap = new HashMap<>();
Map<String, Object> notifySingleMap = new HashMap<>();
for (Map.Entry entry : targetMap.entrySet()) {
String key = entry.getKey().toString();
if (key.indexOf("executors[" + i + "].") != -1) {
if (key.indexOf("executors[" + i + "].notify.") != -1) {
key = key.replace("executors[" + i + "].notify.", "");
String[] notifyKeySplit = key.split("-");
if (notifyKeySplit != null && notifyKeySplit.length > 0) {
key = key.replace("-", "_");
}
notifySingleMap.put(key, entry.getValue());
} else {
key = key.replace("executors[" + i + "].", "");
public interface BootstrapConfigPropertiesBinderAdapt {
String[] keySplit = key.split("-");
if (keySplit != null && keySplit.length > 0) {
key = key.replace("-", "_");
}
executorSingleMap.put(key, entry.getValue());
}
}
if (key.indexOf("notify-platforms[" + i + "].") != -1 || key.indexOf("notifyPlatforms[" + i + "].") != -1) {
if (key.indexOf("notify-platforms[" + i + "].") != -1) {
key = key.replace("notify-platforms[" + i + "].", "");
} else {
key = key.replace("notifyPlatforms[" + i + "].", "");
}
String[] keySplit = key.split("-");
if (keySplit != null && keySplit.length > 0) {
key = key.replace("-", "_");
}
platformSingleMap.put(key, entry.getValue());
}
}
if (CollectionUtil.isEmpty(executorSingleMap) && CollectionUtil.isEmpty(platformSingleMap)) {
break;
}
if (CollectionUtil.isNotEmpty(executorSingleMap)) {
ExecutorProperties executorProperties = BeanUtil.mapToBean(executorSingleMap, ExecutorProperties.class, true);
if (executorProperties != null) {
if (CollectionUtil.isNotEmpty(notifySingleMap)) {
DynamicThreadPoolNotifyProperties alarm = BeanUtil.mapToBean(notifySingleMap, DynamicThreadPoolNotifyProperties.class, true);
alarm.setReceives(alarm.getReceives());
executorProperties.setNotify(alarm);
}
executorPropertiesList.add(executorProperties);
}
}
if (CollectionUtil.isNotEmpty(platformSingleMap)) {
NotifyPlatformProperties notifyPlatformProperties = BeanUtil.mapToBean(platformSingleMap, NotifyPlatformProperties.class, true);
if (notifyPlatformProperties != null) {
notifyPropertiesList.add(notifyPlatformProperties);
}
}
}
bindableConfigProperties = new BootstrapConfigProperties();
bindableConfigProperties.setExecutors(executorPropertiesList);
bindableConfigProperties.setNotifyPlatforms(notifyPropertiesList);
} catch (Exception ex) {
throw ex;
}
return bindableConfigProperties;
}
BootstrapConfigProperties bootstrapCorePropertiesBinder(Map<Object, Object> configInfo, BootstrapConfigProperties bootstrapConfigProperties);
}

@ -0,0 +1,47 @@
/*
* 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 cn.hippo4j.config.springboot.starter.refresher;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import java.util.Map;
/**
* Bootstrap core properties binder adapt.
*/
public class DefaultBootstrapConfigPropertiesBinderAdapt implements BootstrapConfigPropertiesBinderAdapt {
/**
* Bootstrap core properties binder.
*
* @param configInfo
* @param bootstrapConfigProperties
* @return
*/
@Override
public BootstrapConfigProperties bootstrapCorePropertiesBinder(Map<Object, Object> configInfo, BootstrapConfigProperties bootstrapConfigProperties) {
ConfigurationPropertySource sources = new MapConfigurationPropertySource(configInfo);
Binder binder = new Binder(sources);
return binder.bind(BootstrapConfigProperties.PREFIX, Bindable.ofInstance(bootstrapConfigProperties)).get();
}
}

@ -18,6 +18,7 @@
package cn.hippo4j.config.springboot.starter.refresher;
import cn.hippo4j.config.springboot.starter.config.BootstrapConfigProperties;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
@ -38,8 +39,9 @@ public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefres
@NacosInjected
private ConfigService configService;
public NacosRefresherHandler(BootstrapConfigProperties bootstrapConfigProperties) {
super(bootstrapConfigProperties);
public NacosRefresherHandler(NacosConfigProperties nacosConfigProperties) {
super();
this.configService = nacosConfigProperties.configServiceInstance();
}
@Override
@ -47,7 +49,7 @@ public class NacosRefresherHandler extends AbstractConfigThreadPoolDynamicRefres
Map<String, String> nacosConfig = bootstrapConfigProperties.getNacos();
String dataId = nacosConfig.get(DATA_ID);
String group = nacosConfig.get(GROUP);
return configService.getConfig(dataId, group, Long.MAX_VALUE);
return configService.getConfig(dataId, group, 60 * 10000);
}
@Override

@ -15,5 +15,6 @@
<module>hippo4j-spring-boot-starter</module>
<module>hippo4j-spring-boot-starter-adapter</module>
<module>hippo4j-spring-boot-starter-monitor</module>
<module>hippo4j-config-spring-boot-1.5-starter</module>
</modules>
</project>

Loading…
Cancel
Save