相信很多人遇到过这个问题:本地运行的好好的程序,怎么部署到线上就报找不到配置呢?
FieldMapConfig.class.getResource("p1.properties").getPath();
- 这段代码在本地运行没有任何问题,一放到线上就报空指针。
App.class.getClassLoader().getResource("p1.properties").getPath(); FieldMapConfig.class.getResource("p1.properties")
public static void main( String[] args ) { if (args.length != 1) { System.out.println("usage: java -jar com.hyq.simple-1.0.jar args"); return; } System.out.println("App.class.getResource(args[0]):"); System.out.println(App.class.getResource(args[0])); System.out.println(); System.out.println("App.class.getClassLoader().getResource(args[0]):"); System.out.println(App.class.getClassLoader().getResource(args[0])); System.out.println(); System.out.println("App.class.getResourceAsStream(args[0]):"); System.out.println(App.class.getResourceAsStream(args[0])); System.out.println(); System.out.println("App.class.getClassLoader().getResourceAsStream(args[0]):"); System.out.println(App.class.getClassLoader().getResourceAsStream(args[0])); System.out.println(); }
获取到的配置有区别。怎么解释呢?
前者是读取的当前类的包目录下的配置文件
后者读取的是,jar包内部,根目录的配置文件。
总结:当读取配置的路径不是以/开头时,会按相对路径读取,相对的是当前类的class 这个文件,而采用class的classLoader则是相对于根路径(也就是我们说的classpath)。
!/p1.properties" 这样的路径,getResource是无法读取的,因为他不是一个文件路径。
而getResourceAsStream会以流的方式,打开文件来读取数据,上图的文件树,就是我用unzip命令解压jar包后显示出来的。
默认情况下,springboot会加载名为application的properties或者yml文件。
其中查找的顺序为:
注意:重复定义的配置,会被后者覆盖。
相信大家可能遇到过这样一个场景,同一个jar包要启动多次,每个进程的配置不一样,端口不同。
通过--spring.config.name 指定配置文件名即可。
还有一种新奇的方式,直接通过spring.application.json传递json,案例如下:
java -Dspring.application.json='{"name":"test"}' -jar myapp.jar
当然,你也可以指定多个配置文件,方式如下:
java -jar myproject.jar --spring.config.location=classpath:/p1.properties,classpath:/p2.properties
值得注意的是,config配置文件搜索的顺序和指定的顺序是刚好相反的。
通过spring.profiles.active属性可以指定那个环境下的配置。
这里我比较喜欢定义两个yml,然后在application.yml中指定对应环境的配置。
spring: profiles: active: prod
可以通过@value注解来获取变量值
@Value("${app.init.welcome-msg:侠梦的开发笔记}") private String msg;
也可以通过@ConfigurationProperties("app.init")注解,放在类来获取整个配置。
欢迎来公众号【侠梦的开发笔记】 一起交流进步