Java资源路径各种情况总结(classpath)

时间:2022-01-01 14:48:59

搬迁博客[2015-06-05] http://xiaosunzhu.iteye.com/blog/2217336

Java获取资源(getResource的方式)的搜寻顺序是:首先是Bootstrap加载的jar包,然后是扩展加载的jar包,最后是我们自己配置的classpath。这个具体步骤就不详细说明了,如有需要请参考“如何查找Classes”的官方文档。
在实际项目中前两个步骤一般我们不太关心。更多的是需要配置和查找资源文件,如果了解一些关于classpath的知识,就能更准确的找到资源文件。

一些基本信息

获取classpath

一般来说,可以通过System.getProperty(“java.class.path”)来获取classpath。但是有一种情况并不适用,如果程序以jar包方式运行,这样获取的classpath就只有一个,就是运行的jar包文件。但其实classpath并不只有这一个jar包,这只是一个入口jar,真正的classpath还包括该jar包的META-INF/MANIFEST.MF文件中的“Class-Path: ”项。因此该方法并不完全适用。

classpath的父路径

获取到的classpath并不能确定是绝对路径还是相对路径,取决于配置写的是绝对还是相对路径,获取的时候并不会自动转换为绝对路径。因此需要确定如何得到父路径。

  • 以非jar包运行,此时classpath的父路径是工作目录,取自System.getProperty(“user.dir”)。
  • 以jar包运行,该jar包配置的“Class-Path: ”的父路径是该jar包所在目录。

配置classpath

如同上面所说,是否是以jar包运行,classpath的情况的不同的,配置方式也有所差异。配置classpath是为了能够找到class文件(包括jar包中)及资源文件,如果配置目录并不会查找目录下的所有jar包,因此凡是在jar包中的资源需要配置jar包。

  • 以非jar包运行,那么就可以使用java的 -cp 或 -classpath 进行配置,后面跟随的是目录或jar文件,并且支持*通配符匹配多个jar文件,多个classpath以系统路径分隔符进行分隔(通过System.getProperty(“path.separator”)获得,windows是”;”,linux是”:”)。
  • 以jar包运行,使用-cp/-classpath是无效的,必须在META-INF/MANIFEST.MF文件中配置“Class-Path: ”项,包括目录或jar文件,这里并不支持*通配符匹配多个jar文件,需要一一配置,多个classpath以空格分隔。

classpath查找顺序

遍历classpath的顺序与配置的classpath的顺序完全一致。如果是以jar包运行,因为入口是jar包,在System中获取的classpath也是该jar包,因此会先在该jar包中查找,然后再按顺序遍历查找MANIFEST.MF文件中“Class-Path: ”的配置。

总结

由以上特点总结,在配置、或查找资源时,需要注意运行方式。如果以jar包方式运行,而需要读取jar包外的资源,就需要把资源所在的路径(相对路径是相对于jar包所在目录)配置到MANIFEST.MF文件中。

有的时候编写可执行jar包项目,需要获取配置文件,此时,我们其实更希望是这样一种查找顺序:先找文件系统中的配置文件,如果存在,则使用该配置文件,如果不存在,则使用打包在jar中的配置。因为打包时为了使用方便,可以把默认配置放在jar包中,但是如果要自定义配置,一般并不会直接修改jar包中的文件,而是需要将配置放在文件系统中,方便修改。所以一般来说,文件系统的classpath应当优先于jar包进行查找。

资源库支持

之前提供的resource-utils库自0.0.5版本开始,提供支持这种配置查找顺序,方便使用配置文件。

<dependency>
<groupId>net.sunyijun</groupId>
<artifactId>resource-utils</artifactId>
<version>0.0.5</version>
</dependency>