拒绝FileNotFoundException!总结了这几个读取jar包外配置文件的知识点
前言
相信很多人遇到过这个问题:本地运行的好好的程序,怎么部署到线上就报找不到配置呢?
初识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通过动态指定配置名,读取配置。
- 指定读取多个配置文件。
- 不同运行环境获取不同配置的方式。
欢迎来公众号【侠梦的开发笔记】 一起交流进步
拒绝FileNotFoundException!总结了这几个读取jar包外配置文件的知识点的更多相关文章
- scala读取jar包外配置文件的方式
在scala的开发过程中,经常会修改程序的参数,将这些参数放到配置文件中避免了重复编译,打包的过程 这里给出读取配置文件的三种方式 方式一: 这是最常见的读取配置文件方式 val postgprop ...
- 如何读取jar包外的properties文件和log4j.properties
http://jrails.iteye.com/blog/1705464 ***************************************' 一般在项目中使用properties配置文件 ...
- 读取Jar包中的资源问题探究
最近在写一个可执行jar的程序,程序中包含了2个资源包,一个是images,一个是files.问题来了,在Eclipse里开发的时候,当用File类来获取files下面的文件时,没有任何问题.但是当程 ...
- jar包读取jar包内部和外部的配置文件,springboot读取外部配置文件的方法
jar包读取jar包内部和外部的配置文件,springboot读取外部配置文件的方法 用系统属性System.getProperty("user.dir")获得执行命令的目录(网上 ...
- 读取jar内的配置文件
读取jar包内的配置文件,可以使用ResourceBundle,具体具体例子如下 import java.io.BufferedInputStream; import java.io.IOExcept ...
- 读取jar包里面的文件
一.最近做项目的时候,师兄要求读取jar包里面的java文件.在网上查了各种文件以后,终于完成了,在这里和各位朋友分享一下. (一)找到jar包所在的位置. String path="XXX ...
- Jar中的Java程序如何读取Jar包中的资源文件
Jar中的Java程序如何读取Jar包中的资源文件 比如项目的组织结构如下(以idea中的项目为例): |-ProjectName |-.idea/ //这个目录是idea中项目的属性文件夹 |-s ...
- springboot jar启动 读取jar包中相对路径文件报错
jar包启动后读取相对路径文件报异常: Caused by: java.io.FileNotFoundException: class path resource [***.***] cannot b ...
- maven install 读取jar包时出错;error in opening zip file
错误信息: [INFO] ------------------------------------------------------------------------ [ERROR] Failed ...
随机推荐
- 分享 KubeCon 2019 (上海)关于 Serverless 及 Knative 相关演讲会议
有幸参加了 KubeCon 2019 上海大会,并参加了 Knative 及 Serverless 相关的几场分享会,收获满满.这里简单介绍一下各个演讲主题的主要内容.详细的演讲主题文档可以在Kube ...
- 域名拆分 tld
概念 URL Universal Resource Locator ,统一资源定位符. 用处:用来标识互联网资源的唯一地址. 本质:提供了互联网上任一资源地址的通用表示方法. protocol://h ...
- oracle HEXTORAW(c1)
[功能]将一个十六进制构成的字符串转换为二进制 [参数]c1,十六进制的字符串 [返回]字符串 [示例] select HEXTORAW('A123') from dual;
- @loj - 2090@ 「ZJOI2016」旅行者
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 来到了一个新的城市旅行.她发现了这个城市的布局是网格状的 ...
- Android 监听软键盘搜索键
现在很多的Android应用都有了数据搜索功能,在以往的设计上,会使用搜索框+搜索按钮来实现搜索功能: 现在呢,越来越流行的是,去除搜索按钮,直接监听软键盘搜索键,当用户输入完搜索关键字后,直接点击软 ...
- input标签和fmt:formatDate 在jsp中同时使用引号解决办法
input标签和fmt:formatDate 在jsp中同时使用引号解决办法 使用input标签设置默认值value并格式化fmt时间格式处理 格式化前: <input type="d ...
- IO NIO AIO及常用框架概述
概述 nio 同步: 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步: 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需 ...
- Laravel 5.3 用户验证源码探究 (一) 路由与注册
https://blog.csdn.net/realghost/article/details/52558962 简介 Laravel 从 5.2 开始就有了开箱即用的用户验证,5.3 又在 5.2 ...
- sleep usleep nanosleep alarm setitimer使用
sleep使用的是alarm之类的定时器,定时器是使得进程被挂起,使进程处于就绪的状态. signal+alarm定时器 alarm参数的类型为uint, 并且不能填0 #include <st ...
- 推荐几个web前端比较实用的网站
第一次写博客,说实在的有点紧张和兴奋,哈哈哈哈,本人工作了有两年的时间,平时也有做笔记的习惯,但是都做得乱七八糟的,所以就想通过写博客来记录.好了,废话不多说了,先来几个觉得在工作中使用到的,还不错的 ...