拒绝FileNotFoundException!总结了这几个读取jar包外配置文件的知识点

前言

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

初识getResource
案例一
  FieldMapConfig.class.getResource("p1.properties").getPath();
    ```

    - 这段代码在本地运行没有任何问题,一放到线上就报空指针。

###### 案例二

![file](https://graph.baidu.com/resource/22243f231967f8c552ea801577605576.png)

- 读取配置,报错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();

}

- 验证如下:

![file](https://img2018.cnblogs.com/blog/894494/201912/894494-20191229171443615-244970716.jpg)

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

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

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

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

##### 各种路径试验

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

![file](https://img2018.cnblogs.com/blog/894494/201912/894494-20191229171443871-77831805.jpg)

##### 为什么推荐使用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包要启动多次,每个进程的配置不一样,端口不同。

![file](https://img2018.cnblogs.com/blog/894494/201912/894494-20191229171444257-525834636.jpg)

###### 知识点二
通过--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属性可以指定那个环境下的配置。

![file](https://img2018.cnblogs.com/blog/894494/201912/894494-20191229171444449-2036003783.jpg)
这里我比较喜欢定义两个yml,然后在application.yml中指定对应环境的配置。

spring:
profiles:
active: prod
###### 知识点五 可以通过@value注解来获取变量值
@Value("${app.init.welcome-msg:侠梦的开发笔记}")
private String msg;
```
也可以通过@ConfigurationProperties("app.init")注解,放在类来获取整个配置。

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

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

原文地址:https://www.cnblogs.com/hyq0823/p/12115553.html

时间: 2024-08-15 03:14:05

拒绝FileNotFoundException!总结了这几个读取jar包外配置文件的知识点的相关文章

scala读取jar包外配置文件的方式

在scala的开发过程中,经常会修改程序的参数,将这些参数放到配置文件中避免了重复编译,然而打包的过程,如果不做配置文件外置,将无法修改配置内容,还是需要重新打包 这里给出读取配置文件的三种方式 方式一: 这是最常见的读取配置文件方式 val postgprop = new Properties()val ipstream: InputStream = this.getClass().getResourceAsStream("/config.properties")postgprop.

如何读取jar包外的properties文件和log4j.properties

http://jrails.iteye.com/blog/1705464 ***************************************' 一般在项目中使用properties配置文件的时候都将相关的properties文件放在src目录下,在将该app打包生成jar后,相应的properties配置文件生... 一般在项目中使用properties配置文件的时候都将相关的properties文件放在src目录下,在将该app打包生成jar后,相应的properties配置文件生

Spring boot 如何读取jar包外面的properties文件

先来张target跟目录的文件结构 conf文件夹中存放的是properties文件, lib文件夹中存放的是各种jar文件, start.bat是windows命令行的启动文件. 来张properties文件的内容 1. 创建配置文件相关的配置类,每个properties文件对应一个配置类 这里使用了@ConfigurationProperties, prefix是指properties文件中的前缀, 比如 asdf.name, 前缀就是asdf,  实体类中的name对应着asdf后面的na

读取Jar包中的资源问题探究

最近在写一个可执行jar的程序,程序中包含了2个资源包,一个是images,一个是files.问题来了,在Eclipse里开发的时候,当用File类来获取files下面的文件时,没有任何问题.但是当程序导出为Runnable Jar时,运行程序时抛出异常,File not found.我们来一探究竟. 首先是我的工程目录结构: 程序中访问images下的图片代码: [java] view plaincopyprint? setIconImage(new ImageIcon(this.getCla

【动态页面】(三)之二:通过自定义注解读取Jar包的类名和属性名

上篇博客介绍了通过反射读取Jar包的类名和属性名,但是问题是读不出类名和属性名的中文注释和属性类型.所以上篇博客埋下了一个伏笔,就是通过自定义注解的方式读取Jar包的类名.属性名.中文注释和属性类型.这篇博客我们就来好好讲讲是如何实现的. 首先先说一下,由于我们的Jar包没有放到项目下,所以就想着怎么能把Jar包添加进来,所以先做了一个类似于上传文件的功能,将Jar上传进来,然后再读取Jar包里面的类名.属性名等一系列属性,再添加到数据库中.总体的思路确定了,下面就开始实施. 首先是上传Jar包

java读取jar包配置文件

前置条件:使用java -jar XXX.jar运行java程序,其中有部分代码是需要读取jar中的配置文件 问题描述: 发现无法读取到该配置文件 解决思路: 1. 该配置文件没有打到jar包中 2. 该配置文件损坏无法读取 3. 读取配置文件的代码有误 最终方案: 使用new FileInputStrem(file)的方式是无法读取到jar中的配置文件的,改为注释部分代码即可解决.这个链接http://blog.csdn.net/b_h_l/article/details/7767829的文章

换了应用部署环境,读取jar包中文件遇到的问题。

程序换了个tomcat部署出现了问题,在原来的系统里好好的.最后定位问题发现是使用dom4j读取jar包中文件出现的问题,dom4j的异常是:org.dom4j.DocumentException: null Nested exception: null,经过观察发现拿到的InputStream对象为空.再追代码发现是因为JarFile压根就没有读到文件.顺手换成了当前线程上下文去读取文件,这次抛出的异常很清楚,jar文件找不到.最近经过观察发现是引文文件路径中存在空格,这是和原来系统不同的地方

springboot jar启动 读取jar包中相对路径文件报错

jar包启动后读取相对路径文件报异常: Caused by: java.io.FileNotFoundException: class path resource [***.***] cannot be resolved to absolute .***.jar/BOOT-INF/classes!/***.** 采用流的方式读取即可解决 // /template/template.html是resource下面的文件 String template=readfile("/template/tem

maven install 读取jar包时出错;error in opening zip file

错误信息: [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-compile) on project qchat-common: Compilation failure [ERROR] F