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

相关推荐
蓦然回首却已人去楼空7 分钟前
【分词:中文分词】BPE字节级分词算法实现汉字表达!
java·算法·中文分词
asdfg125896315 分钟前
一文理解Java中的泛型
java·开发语言
飞翔中文网15 分钟前
Java学习笔记之反射
java·笔记·学习
河阿里17 分钟前
Spring Boot:整合Quartz集群部署指南
java·spring boot·后端
小肥君30 分钟前
gpu安装milvus问题解决
java·eureka·milvus
砍材农夫31 分钟前
物联网实战:Spring Boot MQTT | 模拟器Paho客户端拆解高性能
java·javascript·spring boot·后端·物联网·struts
电商API_1800790524739 分钟前
免 TOP 入驻,第三方淘宝商品详情 API 快速接入与代码示例
java·大数据·开发语言·数据库·爬虫·数据分析
IT空门:门主40 分钟前
Java AI 开发框架终极对比:Spring AI vs Spring AI Alibaba vs AgentScope-Java
java·人工智能·spring·spring ai·ai alibaba·agentscope-java
未若君雅裁1 小时前
多线程项目场景:CountDownLatch、Future、Semaphore
java
小科先生1 小时前
初学者安装java
java·开发语言