[有图有真相]IDEA下的Maven工程读取properties等资源文件的路径问题


仅供参考,如有错误或不足欢迎留言指正。


我们以maven的web项目为例:
这里写图片描述
接下来我们看看工程结构:这里只讨论src目录和target目录
src目录:

  • src/main/java: java:起初生成maven项目时并没有这个resource文件夹,是建立maven项目后手动添加进去的,用于存放java源文件
  • src/main/resources:存放项目的各种资源(如图片文本之类的)及全局配置文件
  • src/main/webapp:webapp目录是web目录所特有的目录,不作详细介绍

target目录:
- classes:这个就是classpath目录,即存放java字节码文件以及相关配置文件(如properties文件)的根目录,后面会用代码演示资源文件的路径及相关知识
target目录下的其他目录不再做介绍,与本文讨论的知识并无多大关系。

src 与 target: src/main/下的java文件下的.java文件编译后的.class文件及resources文件相关资源文件都会在target/classes中。

关于java的字节码文件存放位置: target/classes目录下会生成对应的相关字节码文件及相关的包文件夹
关于src/main/resources文件:这是一个专门存放各类信息文件的配置文件夹,笔者曾犯的一个错误就是将配置文件放在了java目录下,导致始终无法获取配置文件的输入流

说完了相关文件介绍,我们进入正题:
首先介绍两个方法:getResource(String filePath)getResourceAsStream(String filePath)
getResource(String filePath):下面上代码:
这里写图片描述
分析:通过运行结果我们可以看到通过Class类对象调用getResource(String filePath)方法获取的路径是classes文件下的类路径但不包含类本身;而通过ClassLoader类调用的getResource(String filePath)方法,则输出到classpath的根目录。

ok,说到此处,我觉得有上 API文档的必要了。我们来看看Class和ClassLoader类的getResource(),getResourceAsStream()方法:
Class类的getResource()和getResourceAsStream():
getResource()方法注释:
<li> If the {@code name} begins with a {@code '/'}
* (<tt>'&#92;u002f'</tt>), then the absolute name of the resource is the
* portion of the {@code name} following the {@code '/'}
* <li> Otherwise, the absolute name is of the following form:
* <blockquote>
* {@code modified_package_name/name}
* </blockquote>
* <p> Where the {@code modified_package_name} is the package name of this object with {@code '/'} substituted for {@code '.'}
* (<tt>'&#92;u002e'</tt>).

大致意思是:如果路径名(也就是filePath)以 “/” 开头,那么资源的绝对路径名是文件路径的一部分。否则,其路径名为 “包名/文件名”,最后还特别说明了一下:包名的点被 “/”所替代掉。
getResourceAsStream()注释的资源路径说明与getResource()方法相同,可以自己区查阅API文档。

ClassLoader类的getResource()和getResourceAsStream():
getResource()注释:

* Finds the resource with the given name.  A resource is some data(images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code.
     * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
     * identifies the resource.
     * <p> This method will first search the parent class loader for the
     * resource; if the parent is <tt>null</tt> the path of the class loader
     * built-in to the virtual machine is searched.  That failing, this method
     * will invoke {@link #findResource(String)} to find the resource.  </p>

大致意思是:通过给定的名字搜索资源。这些资源指的是那些可以通过一种不依赖java代码的方式而被java文件所接收的资源(例如:图片,音频,文本等等)。关于搜索规则,其中提到了一个关键点:首先搜索父目录(字节码目录classes)。通过这点,我们已经可以知道该方法的filepath开头是不加”/”的,即从classes目录开始搜索。而关于getResourceAsStream()的搜索规则,文档注释中说与getResource()一样,在此就不再贴注释了。

说的再多,不如贴代码来的直接:
首先在如图mysql.properties文件位置:
这里写图片描述

同时呢,我们可以在classes下看到相关的文件夹config及mysql.properties文件:
这里写图片描述

前面我们提到过,资源的路径取的是classpath(即类加载路径)下的路径。接下来我们要讨论的是分别通过Class及ClassLoader类的getResourceAsStream()方法获取mysql.properites文件流从而获取数据。

public class Test {
    public static void main(String[] args) throws Exception {
        getStreamByClass("/config/mysql.properties");
        getStreamByClassLoader("config/mysql.properties");
    }
    public static void getStreamByClass(String filePath) throws Exception {
        //通过Class的getResourceAsStream()获取properties文件输入流
        InputStream in = Test.class.getResourceAsStream(filePath);
        //当然,也可以通过实例获取Class对象
        InputStream in1 = new Test().getClass().getResourceAsStream(filePath);
        printProperties(in);
        printProperties(in1);
    }
    public static void getStreamByClassLoader(String filePath) throws Exception {
        //通过ClassLoader的getResourceAsStream()获取输入流
        InputStream in = Test.class.getClassLoader().getResourceAsStream(filePath);
        //同样的,通过实例也可以获取ClassLoader对象
        InputStream in1 = new Test().getClass().getClassLoader().getResourceAsStream(filePath);
        printProperties(in);
        printProperties(in1);
    }
    public static void printProperties(InputStream in) throws Exception {
        Properties pro = new Properties();
        pro.load(in);
        System.out.println("url: " + pro.getProperty("url")
                         + "user: " + pro.getProperty("user")
                         + "password: " + pro.getProperty("password"));
    }
}

运行结果如下:
这里写图片描述

扫描二维码关注公众号,回复: 1050321 查看本文章

猜你喜欢

转载自blog.csdn.net/johnyhe/article/details/78324874