编译运行时的资源读取路径

类名.class与getClass()

类名.class与getClass()实际上是一个东西,只不过getClass()获取到的是当前代码下的Class,而类名.class则自由,可以随意指定哪个类文件。
假如有A.class,然后在A中执行getClass(),那此刻可以完全视它们是一个意思。
需要注意的,如果用类名.class形式,那就需要时刻注意查询文件的路径是依据类名.class的位置来了

getResource()与getClassLoader().getResource()

//表示只会在当前调用类所在的同一路径下查找该fileName文件,表示相对路径:
getClass().getResource(fileName)
//如果在fileName前加了"/",表示绝对路径,取classpath根目录/下的该文件:
getClass().getResource("/" + fileName)


//表示只会在根目录下(/)查找该文件:
getClass().getClassLoader().getResource(fileName):
相当于:
getClass().getResource("/" + fileName)

getClass().getResource()具体用法

16243245901.png
如上面的Maven工程目录,StartApp类位于go包下面,我们使用getClass().getResource("start.fxml")时,在resource资源目录下的go目录需要有对应的start.fxml,否则会报错:Location is not set。

补充:不能直接在java包下的go目录存放start.fxml,同样会报错,因为maven项目在java包目录只会扫描java文件,不会扫描资源文件。至于为什么在resource目录下就可以读到,我们编译运行时可以观察target目录,它们最终会合并到一块:
16243250761.png

System.out.println(StartApp.class.getResource("/view/RootLayout.fxml"));
System.out.println(StartApp.class.getClassLoader().getResource("/view/RootLayout.fxml"));
//结果如下:
file:/C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
null
//区别:
class.getResource("/") == class.getClassLoader().getResource("")
//其实,Class.getResource和ClassLoader.getResource本质上是一样的,都是使用ClassLoader.getResource加载资源的。
//Class.getResource真正调用ClassLoader.getResource方法之前,会先获取文件的路径(path不以'/'开头时,默认是从此类所在的包下取资源;path以'/'开头时,则是从项目的ClassPath根下获取资源)。

实际代码样例

第一种:

URL url = 类名.class.getClassLoader().getResource("conf.properties");
URL url = getClass().getClassLoader().getResource("conf.properties");

第二种:

URL url = 类名.class.getClass().getResource("/view/RootLayout.fxml");
URL url = getClass().getResource("/view/RootLayout.fxml");

//第二种通过URL我们可以获取路径信息:

//toString() : file:/C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
String string = url.toString();
//getPath() :  /C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
String path = url.getPath();
//url.getFile() : /C:/Users/Heawill/Desktop/BroadcastSystemNew/target/classes/view/RootLayout.fxml
File file = new File(url.getFile());
//file.getAbsolutePath() :C:\Users\Heawill\Desktop\BroadcastSystemNew\target\classes\view\RootLayout.fxml
String url = file.getAbsolutePath();

Jar包时的资源读取

编译运行时由于存在真实的文件和路径,所以对资源的读写都可以正常进行,但是当打包成jar包,写的话由于jar文件就不支持了。

//无论时编译运行时还是Jar文件时,getClass().getResource("/view/start.fxml")都能读取到对应的文件,只不过通过打印,我们发现路径发生了改变:

//编译运行时:
file:/G:/DevelopProject/BroadcastSystem/target/classes/view/start.fxml
//Jar文件时:
jar:file:/G:/DevelopProject/BroadcastSystem/target/jfx/app/BroadcastSystemNew-1.2-SNAPSHOT.jar!/view/start.fxml

补充

其他方法:

//以下方法返回的是InputStream类型,路径跟非AsStream的方法一样
getClass().getClassLoader().getResourceAsStream(file)
getClass().getResourceAsStream(file)

Maven项目中的/
Maven项目中的/代表的是的ClassPath根路径,即java或resource目录

注意

有时候fxml等其他资源都是直接在IDEA中复制或者剪切,这可能会导致路径虽然没问题,但是也会报错:Location is not set,这直接通过重构工程解决:
16243254571.png

参考

https://blog.csdn.net/suchahaerkang/article/details/100927545