【Spring Boot】(5)、配置文件的随机数和占位符

Spring Boot全局配置文件中支持使用随机数和占位符的方式进行添加属性。

1、随机数

  • ${random.value}

  • ${random.int}

  • ${random.int(max)}

  • ${random.int(min,max)}

  • ${random.long}

  • ${random.long(max)}

  • ${random.long(min,max)}

  • ${random.uuid}

随机数使用的是RandomValuePropertySource类进行解析。注意:在使用IDEA进行随机数配置的时候,不会提示long的第二种和第三种随机数使用方式,博主也是在看RandomValuePropertySource才发现的。

public class RandomValuePropertySource extends PropertySource<Random> {

	/**
	 * Name of the random {@link PropertySource}.
	 */
	public static final String RANDOM_PROPERTY_SOURCE_NAME = "random";

	private static final String PREFIX = "random.";

	private static final Log logger = LogFactory.getLog(RandomValuePropertySource.class);

	public RandomValuePropertySource(String name) {
		super(name, new Random());
	}

	public RandomValuePropertySource() {
		this(RANDOM_PROPERTY_SOURCE_NAME);
	}

	@Override
	public Object getProperty(String name) {
		if (!name.startsWith(PREFIX)) {
			return null;
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Generating random property for '" + name + "'");
		}
		return getRandomValue(name.substring(PREFIX.length()));
	}

	private Object getRandomValue(String type) {
		if (type.equals("int")) {//${random.int}
            //getSource()返回的是泛型T的实际对象,所以nextInt()也就是调用Random类的nextInt()方法
			return getSource().nextInt();
		}
		if (type.equals("long")) {//${random.long}
			return getSource().nextLong();
		}
		String range = getRange(type, "int");
		if (range != null) {
			return getNextIntInRange(range);
		}
		range = getRange(type, "long");
		if (range != null) {
			return getNextLongInRange(range);
		}
		if (type.equals("uuid")) {//${random.uuid}
			return UUID.randomUUID().toString();
		}
		return getRandomBytes();//${random.value}
	}

	private String getRange(String type, String prefix) {
		if (type.startsWith(prefix)) {
			int startIndex = prefix.length() + 1;
			if (type.length() > startIndex) {
				return type.substring(startIndex, type.length() - 1);
			}
		}
		return null;
	}

	private int getNextIntInRange(String range) {
		String[] tokens = StringUtils.commaDelimitedListToStringArray(range);
		int start = Integer.parseInt(tokens[0]);
		if (tokens.length == 1) {//${random.int(value)}
			return getSource().nextInt(start);
		}
        //${random.int(value,max)}
		return start + getSource().nextInt(Integer.parseInt(tokens[1]) - start);
	}

	private long getNextLongInRange(String range) {
		String[] tokens = StringUtils.commaDelimitedListToStringArray(range);
		if (tokens.length == 1) {//${random.long(value)}
			return Math.abs(getSource().nextLong() % Long.parseLong(tokens[0]));
		}
		long lowerBound = Long.parseLong(tokens[0]);
		long upperBound = Long.parseLong(tokens[1]) - lowerBound;
        //${random.long(value,max)}
		return lowerBound + Math.abs(getSource().nextLong() % upperBound);
	}

	private Object getRandomBytes() {
		byte[] bytes = new byte[32];
		getSource().nextBytes(bytes);
        //${random.value}
		return DigestUtils.md5DigestAsHex(bytes);
	}

	//...
}

        博主有一个习惯,就是如果在标点符号后面还有变量啥的,都喜欢在标点符号后面多敲一个空格,方便查看,也保持排版的整洁。在使用${random.int(min,max)}的时候就喜欢敲成${random.int(min, max)},注意逗号和max之间有个空格。当博主写了一个变量${random.long(20000, 99999)},在调试的时候,发现在解析的时候老是报错,后来看异常的时候,才发现无法解析“ 99999”,原来逗号和max之间不能写空格,真是个坑啊!!!

注意点:凡是有写min和max两个value的random,min和max之间不能有空格,只能是逗号,不然在源码解析的时候解析不了,会报异常。如:${random.int(100,200)}是正确的,而${random.int(100, 200)}是错误的,请一定要注意,防止入坑!!!


   

2、占位符

可以引用之前的属性值,如果没有则可以使用默认值。例如:${aaa: default},如果 ${aaa}不存在,则使用default代替aaa的值;如果${aaa}存在,则使用${aaa}的值。


a = ${random.int}
b = ${random.int(100)}
c = ${random.int(500,1000)}
d = ${random.long}
e = ${random.long(10000)}
f = ${random.long(20000,99999)}
g = ${random.value}
h = ${random.uuid}
i = ${aaa:"bbb"}

在解析占位符的时候,例如有个变量i = ${aaa:"bbb"},在引用i变量的时候,会先解析i的值,然后在解析${aaa:"bbb"}的值,接着又解析${aaa}的值,如果存在,则直接使用aaa变量的值,如果不存在,则直接使用"bbb"作为a变量的值,实际上是一种递归解析




====================打个广告,欢迎关注====================

QQ:
412425870
微信公众号:Cay课堂

csdn博客:
http://blog.youkuaiyun.com/caychen
码云:
https://gitee.com/caychen/
github:
https://github.com/caychen

点击群号或者扫描二维码即可加入QQ群:

328243383(1群)




点击群号或者扫描二维码即可加入QQ群:

180479701(2群)




<think>好的,用户想了解如何在配置文件中使用占位符以及相关的最佳实践。首先,我需要回忆一下不同框架或系统中占位符的使用方法。记得Spring BootNacos都有类似的特性,可能还有其他系统比如SSM框架。用户提供的引用里提到了Spring Boot随机数配置值,以及Nacos中的多配置项相同值的情况,还有SSM的config.properties。我需要把这些信息整合起来。 首先,占位符的基本用法是什么?比如在Spring Boot中,使用${}来引用已定义的属性,或者生成随机数。例如${spring.profiles.active}或者${random.int}。然后,Nacos的示例显示多个配置项使用相同的host,这时候用占位符可以减少重复,方便维护。另外,SSM框架中通过替换占位符来动态传入变量,减少重复代码。 接下来要分点说明不同场景下的用法,可能包括基本语法、多级引用、默认值设置、随机数生成、环境变量支持、动态替换等。同时,最佳实践部分需要强调命名规范、默认值的使用、避免循环引用、环境隔离、版本控制等。可能还需要结合用户提供的引用中的例子,比如引用2引用3中的具体配置示例。 需要确保回答结构清晰,步骤明确,涵盖用户可能关心的方面。比如用户可能想知道如何在不同框架中使用,如何处理默认值,如何避免常见错误。同时,生成的相关问题需要围绕占位符的扩展应用、解决配置冲突、Spring Boot与Nacos的区别,以及SSM中的具体实现。 还要注意引用用户提供的参考资料,比如在提到Nacos时引用[^2],提到Spring Boot时引用[^3],SSM时引用[^4]。确保每个引用都自然融入回答中,不显得突兀。 最后,检查是否覆盖了用户可能的疑问,比如占位符的语法、不同系统的差异、最佳实践建议,以及如何处理复杂情况如默认值环境变量。确保回答准确,符合用户的实际需求,并且语言通俗易懂,避免过于技术化的术语,但又要足够详细。</think>以下是关于配置文件占位符的用法及最佳实践的详细说明: --- ### 一、占位符的常见用法 1. **基本语法** 在大多数框架(如Spring Boot、Nacos)中,使用`${属性名}`格式实现占位符,例如: ```properties # 引用已定义的配置项 api.host=http://service.com auth.api1=${api.host}/auth auth.api2=${api.host}/resource ``` 此方式可减少重复配置,便于统一管理。 2. **多级引用** 支持嵌套引用其他占位符: ```properties base.path=/data/logs app.log=${base.path}/app.log ``` 3. **默认值设置** 当引用的属性未定义时,可通过`:`指定默认值: ```properties # 若未定义server.port,则默认使用8080 server.port=${SERVER_PORT:8080} ``` 4. **随机数生成** Spring Boot支持通过占位符生成随机值: ```properties # 生成随机UUID或整数 token=${random.uuid} max.retry=${random.int(5,10)} ``` 此特性常用于测试或临时标识。 5. **环境变量支持** 可直接引用系统环境变量: ```properties # 读取JAVA_HOME环境变量 java.home=${JAVA_HOME} ``` 6. **动态替换** 在SSM框架中,可通过代码替换占位符实现动态配置: ```java // 通过@Value注解注入动态值 @Value("${api.endpoint.${service.type}}") private String endpoint; ``` 这种方式减少了硬编码[^4]。 --- ### 二、最佳实践 1. **命名规范** - 使用层级命名(如`db.master.url`)增强可读性 - 避免使用特殊字符(如`_``-`混用) 2. **默认值设计** - 关键配置必须设置默认值(如`${REDIS_HOST:localhost}`) - 敏感信息禁止设置默认值(如密码、密钥) 3. **避免循环引用** 禁止出现`a=${b}`, `b=${c}`, `c=${a}`的死循环场景 4. **环境隔离** 结合`spring.profiles.active`实现多环境配置: ```properties # 开发环境 spring.datasource.url=${DEV_DB_URL} # 生产环境通过启动参数覆盖 ``` 5. **版本控制** - 将通用配置抽离为独立文件(如`application-common.yml`) - 使用注释标记配置项用途修改记录 --- ### 三、典型问题解决方案 **场景1:配置项冗余** 使用占位符统一基础配置,例如Nacos中多个服务共享同一域名: ```yaml base: domain: example.com serviceA: url: ${base.domain}/api serviceB: url: ${base.domain}/data ``` **场景2:敏感信息处理** 通过环境变量注入真实值,避免明文存储: ```properties # 配置文件 db.password=${DB_PASSWORD} # 启动命令 java -jar app.jar --DB_PASSWORD=**** ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值