@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,那么以上代码则会生效。

相关推荐
神仙别闹17 分钟前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭41 分钟前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫1 小时前
泛型(2)
java
超爱吃士力架1 小时前
邀请逻辑
java·linux·后端
南宫生1 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石1 小时前
12/21java基础
java
李小白661 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp2 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗2 小时前
常用类晨考day15
java