使用ClassLoader加载包内的资源
ClassLoader可以把包(jar包,war包)内的class文件加载到JVM中,第一步就是将class文件以stream的方式读取出来。ClassLoader也将这个加载资源的方法getResourceAsStream暴露了出来。编程时可以使用这个方法来加载包内的任何资源,比如properties文件,图片等。
使用CL加载资源
当使用ClassLoader加载资源的时候,参数应该是资源文件在包内的路径,不以“/”开头。对于下面的package结构:
如果要加载test.properties。getResourceAsStream的参数就是“classloader/getresource/deeper/test2.properties”。
CL可以加载任何一个在classpath上存在的资源文件,可以不是一个package内,也可以不在一个包内。简单来说,只要把资源文件也当作一个类来看待,把类的全路径名中的“.”换成“/”就可以了。
getResourceAsStream的参数也可以有“..”,用来回到上一层目录。
使用Class加载资源文件
Class类也有一个getResourceAsStream方法。对于同一个包中的资源文件,使用Class加载资源文件会更简单。
比如上图中,如果GetResourceInCurrentPkg类想加载test.properties,只要使用下面的代码就行了。
1 | GetResourceInCurrentPkg. class .getResourceAsStream( "test.properties" ) |
Class类也是使用CL去加载资源的。它所做的事情就是将参数修订成CL需要的格式。变化都在Class类的resolveName方法中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** * Add a package name prefix if the name is not absolute Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (name == null ) { return name; } if (!name.startsWith( "/" )) { Class c = this ; while (c.isArray()) { c = c.getComponentType(); } String baseName = c.getName(); int index = baseName.lastIndexOf( '.' ); if (index != - 1 ) { name = baseName.substring( 0 , index).replace( '.' , '/' ) + "/" +name; } } else { name = name.substring( 1 ); } return name; } |
方法含义很简单
- 对于不是以“/”开头的参数,就认为这个路径是相对于当前类的路径,所以加载当前包中的资源只要写资源文件的名字就可以了。方法最大的一块代码就是为了得到当前类的路径,然后和传进来的相对路径参数拼起来,作为资源文件的绝对路径丢给CL。
- 对于以“/”开头的参数,就认为参数是资源文件的绝对路径,将这个斜线去掉之后,丢给CL去加载就行了。
同样,这个方法的参数同样接受“..”来返回上一层目录。
例程
参照下面的图
下面的示例代码可以成功加载资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | package classloader.getresource; import java.io.IOException; import java.util.Properties; public class GetResourceInCurrentPkg { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // using Class.getResourceAsStream, the default location is the package // of current class. It is an instance method, so every instance know // that where is the class, and which package it is, and which class // loader to // use. It is a relative path. Properties props = new Properties(); props.load(GetResourceInCurrentPkg. class .getResourceAsStream( "../getresource/test.properties" )); System.out.println(props.get( "test" )); props = new Properties(); props.load(GetResourceInCurrentPkg. class .getResourceAsStream( "test.properties" )); System.out.println(props.get( "test" )); props = new Properties(); props.load(GetResourceInCurrentPkg. class .getResourceAsStream( "deeper/test2.properties" )); System.out.println(props.get( "test2" )); // if the path start with /, then it means the path is absolute path. props = new Properties(); props.load(GetResourceInCurrentPkg. class .getResourceAsStream( "/classloader/getresource/deeper/test2.properties" )); System.out.println(props.get( "test2" )); // Using class loader, it is always the absolute path. props = new Properties(); props.load(GetResourceInCurrentPkg. class .getClassLoader() .getResourceAsStream( "classloader/getresource/deeper/test2.properties" )); System.out.println(props.get( "test2" )); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?