加载资源可以用绝对路径和相对路径,但都有局限性。用硬编码的方式不好。
比较好的方式是绝对+相对方式。即绝对路径就是应用程序安装的路径,相对路径是资源文件相对于程序根目录的路径。
java.lang.ClassLoader不仅可以加载类到内存中,还可以加载其它的资源。
[size=large]1. ClassLoader.getResourceAsStream[/size]
比方说配置文件,很多时候都是放在源代码路径下的,这样就可以直接使用ClassLoader
这里的conf.properties是放在com.john.basis包下的,编译的时候IDE会帮我们把资源文件拷贝到生成目录。
ClassLoader的getResourceAsStream的操作分成两个部分:getResource()和openStream()。
getSystemResourceAsStream亦是如此。
下面就以getResourceAsStream为例:
如果parent存在,则从parent中getResource();否则从启动引导路径中去找。
如果url还是null,则调用自定义的findResource()去找。
[size=large]2. Class.getResourceAsStream[/size]
jdk帮我们简化了上面的代码,如果conf.properties是和MyClass在同一个目录下,那么可以直接调用类的getResourceAsStream方法:
其实Class类的getResourceAsStream(name)也是调用了ClassLoader.getResourceAsStream(name)方法的:
如果当前的ClassLoader为null,就调用ClassLoader.getSystemResourceAsStream(name)方法。
这里对name进行了预处理:
如果name不是以'/'开头:
替换包名中的.为/,将处理后的字符串作为前缀加到name上去。在这里就是:"com/john/basis" + "/" + "conf.properties"
否则,认为该文件存放在代码根目录,去除首字符'/'。
比较好的方式是绝对+相对方式。即绝对路径就是应用程序安装的路径,相对路径是资源文件相对于程序根目录的路径。
java.lang.ClassLoader不仅可以加载类到内存中,还可以加载其它的资源。
[size=large]1. ClassLoader.getResourceAsStream[/size]
比方说配置文件,很多时候都是放在源代码路径下的,这样就可以直接使用ClassLoader
package com.john.basis;
public class MyClass {
InputStream inputStream = MyClass.class.getClassLoader().getResourceAsStream("com/john/basis/conf.properties");
}
这里的conf.properties是放在com.john.basis包下的,编译的时候IDE会帮我们把资源文件拷贝到生成目录。
ClassLoader的getResourceAsStream的操作分成两个部分:getResource()和openStream()。
getSystemResourceAsStream亦是如此。
下面就以getResourceAsStream为例:
public abstract class ClassLoader {
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
// Sub classes need to override this method
protected URL findResource(String name) {
return null;
}
}
如果parent存在,则从parent中getResource();否则从启动引导路径中去找。
如果url还是null,则调用自定义的findResource()去找。
[size=large]2. Class.getResourceAsStream[/size]
jdk帮我们简化了上面的代码,如果conf.properties是和MyClass在同一个目录下,那么可以直接调用类的getResourceAsStream方法:
InputStream inputStream = MyClass.class.getResourceAsStream("conf.properties");
其实Class类的getResourceAsStream(name)也是调用了ClassLoader.getResourceAsStream(name)方法的:
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
如果当前的ClassLoader为null,就调用ClassLoader.getSystemResourceAsStream(name)方法。
这里对name进行了预处理:
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;
}
如果name不是以'/'开头:
替换包名中的.为/,将处理后的字符串作为前缀加到name上去。在这里就是:"com/john/basis" + "/" + "conf.properties"
否则,认为该文件存放在代码根目录,去除首字符'/'。