大连之窗_综合信息门户网站
您当前的位置 : 大连之窗  >  汽车
拒绝FileNotFoundException!几个读取jar包外配置文件的知识点
2020-03-30 17:40:43 来源:互联网 阅读:-
前言

相信很多人遇到过这个问题:本地运行的好好的程序,怎么部署到线上就报找不到配置呢?

初识getResource


案例一
  FieldMapConfig.class.getResource("p1.properties").getPath();
    - 这段代码在本地运行没有任何问题,一放到线上就报空指针。
案例二

  • 读取配置,报错FileNotFoundException。
  • 乍一看,两段代码好像没有什么区别,但是细心的你,应该发现:
App.class.getClassLoader().getResource("p1.properties").getPath();FieldMapConfig.class.getResource("p1.properties")
  • 一个使用当前class的api,一个使用的当前class的classLoader的api来获取的,这有什么区别呢?请听我细细分说。
Class和ClassLoader


  • 秉着探索的态度,我写了一个例子,请看:
  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();    }


  • 验证如下:

  • 从上图可以看出,使用当前类的GetResource和当前类的classloader的getResource,
    获取到的配置有区别。怎么解释呢?

前者是读取的当前类的包目录下的配置文件

后者读取的是,jar包内部,根目录的配置文件。

总结:当读取配置的路径不是以/开头时,会按相对路径读取,相对的是当前类的class 这个文件,而采用class的classLoader则是相对于根路径(也就是我们说的classpath)。


各种路径试验


  • 如果你还在为相对路径,配置文件前面带不带/,等一系列问题折腾,那不如动手做做试验看看,代码还是上面那段代码,通过动态传入配置文件的路径来读取,试验结果如下:

为什么推荐使用getResourceAsStream?


  • 形如:"jar:file:/data/simpleJava/com.hyq.simple-1.0.jar
    !/p1.properties" 这样的路径,getResource是无法读取的,因为他不是一个文件路径。
    而getResourceAsStream会以流的方式,打开文件来读取数据,上图的文件树,就是我用unzip命令解压jar包后显示出来的。
springboot加载配置

默认情况下,springboot会加载名为application的properties或者yml文件。其中查找的顺序为:

  • 1、当前jar包所在目录的config目录下。
  • 2、当前目录。
  • 3、jar包内classpath的config目录。
  • 4、jar包内classpath目录。

注意:重复定义的配置,会被后者覆盖。

通过名字动态加载配置?


知识点一
  • boot配置的语法是,凡是以--开头(两个横线)的配置,会被解析。
    相信大家可能遇到过这样一个场景,同一个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")注解,放在类来获取整个配置。


总结
  • 本章节我们做了实验,了解了getResource和getResourceAsStream的区别。
  • 学习了springboot通过动态指定配置名,读取配置。
  • 指定读取多个配置文件。
  • 不同运行环境获取不同配置的方式。

欢迎来公众号【侠梦的开发笔记】 一起交流进步

推荐阅读:叶紫网

频道推荐
  • 四川邛崃最出名面食,因面汤如奶而得名,当地人每天都要吃
    四川邛崃最出名面食,因面汤如奶而得名,当地人

    最近宅在家,每天思考吃什么?一人食来说,最简单的就是煮个面了。今天煮面的时候突然分外想念在邛崃吃过的奶汤面,那美味令人难忘。邛崃这个城市,可能有不少人都不知道在...

    2020-02-18
  • 2020年最热门的旅游目的地(前十)
    2020年最热门的旅游目的地(前十)

    在日趋全球化的今天,各个国家之间的联系也日益紧密,出国旅游也成为了一种趋势。对于很多国家来讲,旅游业甚至是关系国计民生的支柱产业,绝大多数发达国家也十分重视旅游...

    2020-02-18
  • 泰国真是越夜越美:夜游清迈,梦回兰纳王朝
    泰国真是越夜越美:夜游清迈,梦回兰纳王朝

    华灯初上,清迈的夜苏醒了。来到清迈,想必你已经饥肠辘辘了,好在清迈各个地方都有夜市,不用走几步便能大快朵颐。香蕉煎饼、水果沙冰、泰北酸肉、香兰叶鸡蛋烧都是游客来...

    2020-02-18
  • 温州瑞安入住的酒店,早餐最好吃的是两碗面,错过玉海楼下次再去
    温州瑞安入住的酒店,早餐最好吃的是两碗面,错

    此次瑞安之行我们住在万松路的星程酒店,价位大概200多元。朋友们看着我的文章,一般很少会看到很贵的酒店,我们选择的大多数是经济舒适型的酒店和旅馆,工薪阶层量入而...

    2020-02-18
  • 中国最适合自驾的3大美丽线路,你心动了吗
    中国最适合自驾的3大美丽线路,你心动了吗

    1、草原天路被誉为“中国的66号公路”的草原天路,承载着无数过客的传说。每年的6月~8月,是草原绽放的时节,一望无际的绿,是公路两旁最极致的风景。自驾路线:人们...

    2020-02-18
  • 在家坐享!洛阳四季不掉线的美景,每一帧都是前所未见!【云游洛阳】
    在家坐享!洛阳四季不掉线的美景,每一帧都是前

    宅在家里的第N天,吃吃睡睡、刷刷抖音、逗逗宠物……为了不让大家宅出“蘑菇”,躺在床上也可以“游山玩水”,小编今天又来放送美景诱惑啦~【云游洛阳】第三期:白云山、...

    2020-02-18