HOCON跨文件变量替换失效问题求助
兄弟我太懂你这个挫败感了!之前用HOCON做多环境配置的时候,也踩过这个跨文件变量替换的坑,给你梳理下问题根源和解决办法!
你现在的问题是:在local.conf里定义了SECRET变量,然后引入app.conf,但app.conf里用${SECRET}提示找不到变量,可把变量和引用放在同一个文件里就完全正常。
核心问题根源
其实大概率是配置加载顺序或者主配置文件指定错误导致的,HOCON的include是把被引入文件的内容直接内联到include语句的位置,理论上你现在的写法是可行的,我给你拆解下可能的问题:
可能的原因&解决办法
原因1:没正确指定加载
local.conf作为主配置
很多Java服务器默认会加载application.conf,如果你启动的时候没明确指定用local.conf,程序可能直接加载了app.conf(或者通过application.conf间接加载),这时候app.conf里的${SECRET}会去查系统环境变量,而你环境变量里没设这个值,自然就报错了。
解决办法:启动服务的时候通过JVM参数指定主配置文件:# 如果local.conf在类路径根目录(比如src/main/resources) java -Dconfig.resource=local.conf -jar your-server.jar # 如果是本地绝对路径的文件 java -Dconfig.file=/Users/xxx/conf/local.conf -jar your-server.jar原因2:变量查找优先级搞混了
HOCON里${SECRET}会先找系统环境变量,再找配置文件里的顶级变量。如果你的系统环境变量里恰好有个同名的SECRET但值为空或者无效,也可能触发异常。你可以先检查下:- Linux/macOS终端输入:
echo $SECRET - Windows cmd输入:
echo %SECRET%
如果有输出但不是你要的fooBar,要么删掉环境变量,要么确认配置里的变量能正常覆盖环境变量。
- Linux/macOS终端输入:
保险写法小技巧
要是还是踩坑,你可以给app.conf里的引用加个可选标记,这样即使变量暂时没找到也不会直接报错,等local.conf的变量加载后会自动覆盖:app.conf修改成:
z { useSecret: ${?SECRET} }
local.conf保持原来的写法就行:
SECRET: "fooBar" include "app.conf"
另外你还可以写个几行的Java小代码,加载配置后打印出z.useSecret的值,快速验证配置是不是真的被正确解析了,比如:
import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; public class ConfigTest { public static void main(String[] args) { Config config = ConfigFactory.load("local").resolve(); System.out.println(config.getString("z.useSecret")); } }
内容来源于stack exchange

