@Value 读取环境变量配置

在项目开发过程中,有必要使用一些灰色规则(即仅用于开发使用过程中的逻辑控制变量)。

比如,本地开发中,一些业务逻辑需要调用第三方代码,但又在本地调不通,怎么办。只能通过 if(本地开发) {mock数据或直接不调用} else {实际三方接口调用}。

这种方式可以使用@Value注解读取环境变量的方式来实现。

@Value属于spring的注解,在spring-beans包下,可以在 字段 或 方法参数 或 构造函数参数 上使用,通常用于属性注入。支持SpEL (Spring Expression Language)表达式来注入值,同时也支持属性占位符注入值。

使用@Value前提:

不能直接作用于静态变量(static);

不能直接作用于常量(final);

不能在非注册的类中使用(类需要被注册在spring上下文中,如用@Service,@RestController,@Component等);

使用这个类时,只能通过依赖注入的方式,用new的方式是不会自动注入这些配置的

java 复制代码
@Value("${spring.application.name:somnus}") 代表的是假如application当中读不到值,那么就使用somnus。这样可以完全避免没有设置值而启动报错的问题。当然也可以不设置默认值,比如@Value("${spring.application.name:}") 这样同样可以避免没有设置值启动报错的问题!

使用@Value("${环境变量名}")就可以直接读取到操作系统的环境变量,就算在properties或者yaml中指定同名属性值也会被系统环境变量值所覆盖,所以在平常自定义属性时避免与系统环境变量重名,最好加上前缀。

笔者定义了这个字段注解

java 复制代码
@Value("${test.ptVerify:}")
private String pressureTestVerify;

但是又不想在 application.yaml中定义,想直接通过 环境变量注入。

这里的问题在于,这里的ptVerify是 驼峰命名[破涕为笑],又有点号

在k8s的configMap里,先定义了

test.ptVerify,发现不行(在控制台也查不到这个环境变量,应该是 环境变量里不允许有 点)

test_ptVerify 不行,spring不识别

test_pt_verify 不行

最后可以工作的为

TEST_PTVERIFY

即全大写形式

SpringBoot的解释如下:

bash 复制代码
Binding From Environment Variables
Most operating systems impose strict rules around the names that can be used for environment variables. For example, Linux shell variables can contain only letters (a to z or A to Z), numbers (0 to 9) or the underscore character (_). By convention, Unix shell variables will also have their names in UPPERCASE.

Spring Boot's relaxed binding rules are, as much as possible, designed to be compatible with these naming restrictions.

To convert a property name in the canonical-form to an environment variable name you can follow these rules:

Replace dots (.) with underscores (_).

Remove any dashes (-).

Convert to uppercase.

For example, the configuration property spring.main.log-startup-info would be an environment variable named SPRING_MAIN_LOGSTARTUPINFO.

debug了下 代码,相应的处理逻辑在类SystemEnvironmentPropertySource

java 复制代码
	protected final String resolvePropertyName(String name) {
		Assert.notNull(name, "Property name must not be null");
		String resolvedName = checkPropertyName(name);
		if (resolvedName != null) {
			return resolvedName;
		}
		String uppercasedName = name.toUpperCase();
		if (!name.equals(uppercasedName)) {
			resolvedName = checkPropertyName(uppercasedName);
			if (resolvedName != null) {
				return resolvedName;
			}
		}
		return name;
	}

	@Nullable
	private String checkPropertyName(String name) {
		// Check name as-is
		if (this.source.containsKey(name)) {
			return name;
		}
		// Check name with just dots replaced
		String noDotName = name.replace('.', '_');
		if (!name.equals(noDotName) && this.source.containsKey(noDotName)) {
			return noDotName;
		}
		// Check name with just hyphens replaced
		String noHyphenName = name.replace('-', '_');
		if (!name.equals(noHyphenName) && this.source.containsKey(noHyphenName)) {
			return noHyphenName;
		}
		// Check name with dots and hyphens replaced
		String noDotNoHyphenName = noDotName.replace('-', '_');
		if (!noDotName.equals(noDotNoHyphenName) && this.source.containsKey(noDotNoHyphenName)) {
			return noDotNoHyphenName;
		}
		// Give up
		return null;
	}

组件类,@Value必须在SpringBoot的组件中使用

java 复制代码
@Component
public class ProfileValueInit {

    @Value("${spring.profiles.active:}")
    private String profile;

    @Value("${test.verify:}")
    private String verifyTest;

    @Value("${test.ptVerify:}")
    private String pressureTestVerify;

    @PostConstruct
    public void init() {
        if (profile != null && profile.contains("local")) {
            ProfileUtils.MOCK_VALUE = true;
        }

        if ("true".equals(verifyTest)) {
            ProfileUtils.TEST_VERIFY = true;
        }

        if ("true".equals(pressureTestVerify)) {
            ProfileUtils.PRESSURE_TEST_VERIFY = true;
        }
    }
}

方法类

java 复制代码
public class ProfileUtils {

    public static boolean MOCK_VALUE;

    public static boolean TEST_VERIFY;

    public static boolean PRESSURE_TEST_VERIFY;

    public static boolean isMockEnv() {
        return MOCK_VALUE;
    }

    public static boolean isTestVerify() {
        return TEST_VERIFY;
    }

    public static boolean isPressureTestVerify() {
        return PRESSURE_TEST_VERIFY;
    }
}

业务类

java 复制代码
// 压测模拟
boolean pt = ProfileUtils.isPressureTestVerify();
if (pt) {
   //做模拟逻辑处理
}

使用set | grep PT查看环境变量,发现有环境变量TEST_PTVERIFY=true,那么以上代码则会生效。

相关推荐
Lojarro6 分钟前
JavaEE基础之- Servlet相关
java·servlet·java-ee
KingDol_MIni28 分钟前
Spring Boot 集成 T-io 实现客户端服务器通信
java·服务器·spring boot
许苑向上32 分钟前
Java八股文(下)
java·开发语言
后端码匠33 分钟前
Spring Boot3+Vue2极速整合:10分钟搭建DeepSeek AI对话系统
人工智能·spring boot·后端
逸Y 仙X37 分钟前
Git常见命令--助力开发
java·大数据·git·java-ee·github·idea
独孤求败Ace41 分钟前
第44天:Web开发-JavaEE应用&反射机制&类加载器&利用链&成员变量&构造方法&抽象方法
java·开发语言
FLZJ_KL41 分钟前
【设计模式】【创建型模式】单例模式(Singleton)
java·单例模式·设计模式
CL_IN1 小时前
企业数据集成:实现高效调拨出库自动化
java·前端·自动化
计算机-秋大田1 小时前
基于Spring Boot的农产品智慧物流系统设计与实现(LW+源码+讲解)
java·开发语言·spring boot·后端·spring·课程设计
计算机毕设指导61 小时前
基于SpringBoot的城乡商城协作系统【附源码】
java·spring boot·后端·mysql·spring·tomcat·maven