完善 yudao-spring-boot-starter-env 组件,完成 registry 组件
							parent
							
								
									d0ce24a2f6
								
							
						
					
					
						commit
						2faaa65325
					
				| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
 | 
			
		||||
    "token": "test1",
 | 
			
		||||
    "adminTenentId": "1",
 | 
			
		||||
    "tag": "${HOSTNAME}",
 | 
			
		||||
 | 
			
		||||
    "appApi": "http://127.0.0.1:48080/app-api",
 | 
			
		||||
    "appToken": "test1",
 | 
			
		||||
| 
						 | 
				
			
			@ -15,8 +16,10 @@
 | 
			
		|||
    "baseUrl": "http://127.0.0.1:48080/admin-api",
 | 
			
		||||
    "systemBaseUrl": "http://127.0.0.1:48080/admin-api",
 | 
			
		||||
    "infaBaseUrl": "http://127.0.0.1:48080/admin-api",
 | 
			
		||||
 | 
			
		||||
    "token": "test1",
 | 
			
		||||
    "adminTenentId": "1",
 | 
			
		||||
    "tag": "${HOSTNAME}",
 | 
			
		||||
 | 
			
		||||
    "appApi": "http://127.0.0.1:8888/app-api",
 | 
			
		||||
    "appToken": "test1",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import me.zhyd.oauth.cache.AuthStateCache;
 | 
			
		|||
import me.zhyd.oauth.config.AuthConfig;
 | 
			
		||||
import me.zhyd.oauth.config.AuthSource;
 | 
			
		||||
import me.zhyd.oauth.request.AuthRequest;
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
package cn.iocoder.yudao.framework.env.config;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.env.core.util.EnvUtils;
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.env.EnvironmentPostProcessor;
 | 
			
		||||
import org.springframework.core.env.ConfigurableEnvironment;
 | 
			
		||||
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.env.core.util.EnvUtils.HOST_NAME_VALUE;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 多环境的 {@link EnvEnvironmentPostProcessor} 实现类
 | 
			
		||||
 * 将 yudao.env.tag 设置到 dubbo、nacos 等组件对应的 tag 配置项,当且仅当它们不存在时
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
public class EnvEnvironmentPostProcessor implements EnvironmentPostProcessor {
 | 
			
		||||
 | 
			
		||||
    private static final Set<String> TARGET_TAG_KEYS = SetUtils.asSet(
 | 
			
		||||
            "spring.cloud.nacos.discovery.metadata.tag", // Nacos 注册中心
 | 
			
		||||
            "dubbo.provider.tag", // Dubbo 服务提供者的 tag
 | 
			
		||||
            "dubbo.consumer.tag" // Dubbo 服务消费者的 tag
 | 
			
		||||
            // MQ TODO
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
 | 
			
		||||
        // 0. 设置 ${HOST_NAME} 兜底的环境变量
 | 
			
		||||
        String hostNameKey = StrUtil.subBetween(HOST_NAME_VALUE, "{", "}");
 | 
			
		||||
        if (!environment.containsProperty(hostNameKey)) {
 | 
			
		||||
            environment.getSystemProperties().put(hostNameKey, EnvUtils.getHostName());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 1.1 如果没有 yudao.env.tag 配置项,则不进行配置项的修改
 | 
			
		||||
        String tag = EnvUtils.getTag(environment);
 | 
			
		||||
        if (StrUtil.isEmpty(tag)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // 1.2 需要修改的配置项
 | 
			
		||||
        for (String targetTagKey : TARGET_TAG_KEYS) {
 | 
			
		||||
            String targetTagValue = environment.getProperty(targetTagKey);
 | 
			
		||||
            if (StrUtil.isNotEmpty(targetTagValue)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            environment.getSystemProperties().put(targetTagKey, tag);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,15 +1,19 @@
 | 
			
		|||
package cn.iocoder.yudao.framework.env.config;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.springframework.boot.context.properties.ConfigurationProperties;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 环境
 | 
			
		||||
 * 环境配置
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@ConfigurationProperties(prefix = "yudao.env")
 | 
			
		||||
@Data
 | 
			
		||||
public class EnvProperties {
 | 
			
		||||
 | 
			
		||||
    public static final String TAG_KEY = "yudao.env.tag";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 环境标签
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.env.config;
 | 
			
		|||
import cn.iocoder.yudao.framework.env.core.fegin.EnvLoadBalancerClientFactory;
 | 
			
		||||
import cn.iocoder.yudao.framework.env.core.fegin.EnvRequestInterceptor;
 | 
			
		||||
import org.springframework.beans.factory.ObjectProvider;
 | 
			
		||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
 | 
			
		||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
 | 
			
		||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
 | 
			
		||||
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +19,7 @@ import java.util.List;
 | 
			
		|||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
@EnableConfigurationProperties(EnvProperties.class)
 | 
			
		||||
public class YudaoEnvRpcAutoConfiguration {
 | 
			
		||||
 | 
			
		||||
    // ========== Feign 相关 ==========
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.env.config;
 | 
			
		|||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.env.core.web.EnvWebFilter;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 | 
			
		||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
 | 
			
		||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +15,7 @@ import org.springframework.context.annotation.Configuration;
 | 
			
		|||
 */
 | 
			
		||||
@Configuration
 | 
			
		||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
 | 
			
		||||
@EnableConfigurationProperties(EnvProperties.class)
 | 
			
		||||
public class YudaoEnvWebAutoConfiguration {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,11 +49,13 @@ public class EnvLoadBalancerClient implements ReactorServiceInstanceLoadBalancer
 | 
			
		|||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Mono<Response<ServiceInstance>> choose(Request request) {
 | 
			
		||||
        // 情况一,没有 tag 时,使用默认的 reactiveLoadBalancer 实现负载均衡
 | 
			
		||||
        String tag = EnvContextHolder.getTag();
 | 
			
		||||
        if (StrUtil.isEmpty(tag)) {
 | 
			
		||||
            return Mono.from(reactiveLoadBalancer.choose(request));
 | 
			
		||||
        }
 | 
			
		||||
        // 选择实例
 | 
			
		||||
 | 
			
		||||
        // 情况二,有 tag 时,使用 tag 匹配服务实例
 | 
			
		||||
        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
 | 
			
		||||
        return supplier.get(request).next().map(list -> getInstanceResponse(list, tag));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,12 @@
 | 
			
		|||
package cn.iocoder.yudao.framework.env.core.util;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.net.NetUtil;
 | 
			
		||||
import cn.hutool.core.util.IdUtil;
 | 
			
		||||
import cn.hutool.core.util.StrUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.env.config.EnvProperties;
 | 
			
		||||
import feign.RequestTemplate;
 | 
			
		||||
import org.springframework.cloud.client.ServiceInstance;
 | 
			
		||||
import org.springframework.core.env.Environment;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,21 +20,32 @@ public class EnvUtils {
 | 
			
		|||
 | 
			
		||||
    private static final String HEADER_TAG = "tag";
 | 
			
		||||
 | 
			
		||||
    private static final String HOST_NAME_VALUE = "${HOSTNAME}";
 | 
			
		||||
    public static final String HOST_NAME_VALUE = "${HOSTNAME}";
 | 
			
		||||
 | 
			
		||||
    public static String getTag(HttpServletRequest request) {
 | 
			
		||||
        String tag = request.getHeader(HEADER_TAG);
 | 
			
		||||
        // 如果请求的是 "${HOSTNAME}",则解析成对应的本地主机名
 | 
			
		||||
        // 目的:特殊逻辑,解决 IDEA Rest Client 不支持环境变量的读取,所以就服务器来做
 | 
			
		||||
        return Objects.equals(tag, HOST_NAME_VALUE) ? NetUtil.getLocalHostName() : tag;
 | 
			
		||||
        return Objects.equals(tag, HOST_NAME_VALUE) ? getHostName() : tag;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String getTag(ServiceInstance instance) {
 | 
			
		||||
        return instance.getMetadata().get(HEADER_TAG);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String getTag(Environment environment) {
 | 
			
		||||
        String tag = environment.getProperty(EnvProperties.TAG_KEY);
 | 
			
		||||
        // 如果请求的是 "${HOSTNAME}",则解析成对应的本地主机名
 | 
			
		||||
        // 目的:特殊逻辑,解决 IDEA Rest Client 不支持环境变量的读取,所以就服务器来做
 | 
			
		||||
        return Objects.equals(tag, HOST_NAME_VALUE) ? getHostName() : tag;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void setTag(RequestTemplate requestTemplate, String tag) {
 | 
			
		||||
        requestTemplate.header(HEADER_TAG, tag);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String getHostName() {
 | 
			
		||||
        return StrUtil.blankToDefault(NetUtil.getLocalHostName(), IdUtil.fastSimpleUUID());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 | 
			
		||||
  cn.iocoder.yudao.framework.env.config.YudaoEnvWebAutoConfiguration,\
 | 
			
		||||
  cn.iocoder.yudao.framework.env.config.YudaoEnvRpcAutoConfiguration
 | 
			
		||||
 | 
			
		||||
org.springframework.boot.env.EnvironmentPostProcessor=\
 | 
			
		||||
    cn.iocoder.yudao.framework.env.config.EnvEnvironmentPostProcessor
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
POST {{systemBaseUrl}}/system/auth/login
 | 
			
		||||
Content-Type: application/json
 | 
			
		||||
tenant-id: {{adminTenentId}}
 | 
			
		||||
tag: 123
 | 
			
		||||
tag: {{tag}}
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  "username": "admin",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,6 +137,8 @@ wx: # 参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-sta
 | 
			
		|||
 | 
			
		||||
# 芋道配置项,设置当前项目所有自定义的配置
 | 
			
		||||
yudao:
 | 
			
		||||
  env: # 多环境的配置项
 | 
			
		||||
    tag: ${HOSTNAME}
 | 
			
		||||
  captcha:
 | 
			
		||||
    enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试
 | 
			
		||||
  security:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,66 +0,0 @@
 | 
			
		|||
package cn.iocoder.mall.dubbo.config;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.common.framework.util.OSUtils;
 | 
			
		||||
import cn.iocoder.common.framework.util.StringUtils;
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
import org.springframework.boot.env.EnvironmentPostProcessor;
 | 
			
		||||
import org.springframework.core.env.ConfigurableEnvironment;
 | 
			
		||||
import org.springframework.core.env.MapPropertySource;
 | 
			
		||||
import org.springframework.core.env.MutablePropertySources;
 | 
			
		||||
import org.springframework.core.env.PropertySource;
 | 
			
		||||
import org.springframework.util.CollectionUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Dubbo 配置项的后置处理器,主要目的如下:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. 生成 {@link #DUBBO_TAG_PROPERTIES_KEY} 配置项,可用于本地开发环境下的 dubbo.provider.tag 配置项
 | 
			
		||||
 */
 | 
			
		||||
public class DubboEnvironmentPostProcessor implements EnvironmentPostProcessor {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 默认配置项的 PropertySource 名字
 | 
			
		||||
     */
 | 
			
		||||
    private static final String PROPERTY_SOURCE_NAME = "mallDubboProperties";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Dubbo 路由标签属性 KEY
 | 
			
		||||
     */
 | 
			
		||||
    private static final String DUBBO_TAG_PROPERTIES_KEY = "DUBBO_TAG";
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
 | 
			
		||||
        // 需要修改的配置项
 | 
			
		||||
        Map<String, Object> modifyProperties = new HashMap<>();
 | 
			
		||||
        // 生成 DUBBO_TAG_PROPERTIES_KEY,使用 hostname
 | 
			
		||||
        String dubboTag = OSUtils.getHostName();
 | 
			
		||||
        if (!StringUtils.hasText(dubboTag)) {
 | 
			
		||||
            dubboTag = StringUtils.uuid(true); // 兜底,强行生成一个
 | 
			
		||||
        }
 | 
			
		||||
        modifyProperties.put(DUBBO_TAG_PROPERTIES_KEY, dubboTag);
 | 
			
		||||
        // 添加到 environment 中,排在最优,最低优先级
 | 
			
		||||
        addOrReplace(environment.getPropertySources(), modifyProperties);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void addOrReplace(MutablePropertySources propertySources, Map<String, Object> map) {
 | 
			
		||||
        if (CollectionUtils.isEmpty(map)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // 情况一,如果存在 defaultProperties 的 PropertySource,则进行 key 的修改
 | 
			
		||||
        if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
 | 
			
		||||
            PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
 | 
			
		||||
            if (source instanceof MapPropertySource) {
 | 
			
		||||
                MapPropertySource target = (MapPropertySource) source;
 | 
			
		||||
                for (String key : map.keySet()) {
 | 
			
		||||
                    target.getSource().put(key, map.get(key));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // 情况二,不存在 defaultProperties 的 PropertySource,则直接添加到其中
 | 
			
		||||
        propertySources.addLast(new MapPropertySource(PROPERTY_SOURCE_NAME, map));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
org.springframework.boot.env.EnvironmentPostProcessor=\
 | 
			
		||||
    cn.iocoder.mall.dubbo.config.DubboEnvironmentPostProcessor
 | 
			
		||||
		Loading…
	
		Reference in New Issue