class.getResource("/").getPath()返回null的问题

 二维码 551
发表时间:2016-08-10 23:44

在做Java应用程序或服务器开发时,我们经常会与配置文件打交道,这样就遇到各种路径问题,什么相对路径,绝对路径,class路径,项目路径等等。但是由于IDE和jar包运行环境不同,也造成了路径的获取方法不一样。一般来说,要获取的路径有以下几中:

一,jar包外的配置文件

  这种配置文件非好弄,只要取相对路径即可,比如,在和jar包同目录下,有一个config/server_config.properties的配置文件,那么在程序中只需要这种就行:File file = new File("config/server_config.properties"),读取即可。

二,jar包内的文件

  比如我们在程序启动时,想加载程序中的某些class类,在eclipse中,我们一般这样获取它的绝对路径:String path = Test.class.getResource("/").getPath() + 相对路径;在eclipse中这样是成功的,因为它获取的是你运行下的classes中的信息,但是如果把程序打成jar再发布的时候,这些class都会被放在一个压缩的jar文件中,这个时候 Test.class.getResource("/").getPath() 返回的就是null,无法获取路径。比如,我们往往有这样的需求,在程序启动时,根据包名的配置,提前加载一些class信息,有可能调用class.newInstance(); 等方法。这样获取路径就不可以了。

幸好有另外一种方法

/**

*

* 描述:这个方法是根据包路径,获取这个包下的所有class

*/

public static List<Class<?>> getClasssFromPackage(String pack) {

// 第一个class类的集合

List<Class<?>> classes = new ArrayList<Class<?>>();


// 获取包的名字 并进行替换

String packageName = pack;

String packageDirName = packageName.replace('.', '/');

// 定义一个枚举的集合 并进行循环来处理这个目录下的things

Enumeration<URL> dirs;

try {

dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);


// 获取下一个元素

URL url = dirs.nextElement();

// 得到协议的名称

String protocol = url.getProtocol();

// 如果是以文件的形式保存在服务器上

if ("file".equals(protocol)) {

classes = getClassFromFile(packageName);

} else if ("jar".equals(protocol)) {

classes = getClassFromJar(url, packageName, packageDirName);

}

} catch (IOException e) {

e.printStackTrace();

}


return classes;

}


private static List<Class<?>> getClassFromJar(URL url, String packageName, String packageDirName) {

List<Class<?>> classes = CollectionUtil.createArrayList();

// 如果是jar包文件

// 定义一个JarFile

JarFile jar;

// 是否循环迭代

boolean recursive = true;

try {

// 获取jar

jar = ((JarURLConnection) url.openConnection()).getJarFile();

// 从此jar包 得到一个枚举类

Enumeration<JarEntry> entries = jar.entries();

// 同样的进行循环迭代

while (entries.hasMoreElements()) {

// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件

JarEntry entry = entries.nextElement();

String name = entry.getName();

// 如果是以/开头的

if (name.charAt(0) == '/') {

// 获取后面的字符串

name = name.substring(1);

}

// 如果前半部分和定义的包名相同

if (name.startsWith(packageDirName)) {

int idx = name.lastIndexOf('/');

// 如果以"/"结尾 是一个包

if (idx != -1) {

// 获取包名 把"/"替换成"."

packageName = name.substring(0, idx).replace('/', '.');

}

// 如果可以迭代下去 并且是一个包

if ((idx != -1) || recursive) {

// 如果是一个.class文件 而且不是目录

if (name.endsWith(".class") && !entry.isDirectory()) {

// 去掉后面的".class" 获取真正的类名

String className = name.substring(packageName.length() + 1, name.length() - 6);

try {

// 添加到classes

classes.add(Class.forName(packageName + '.' + className));

} catch (ClassNotFoundException e) {

// log

// .error("添加用户自定义视图类错误

// 找不到此类的.class文件");

e.printStackTrace();

}

}

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

return classes;

}


代码中有详细的注释,这个代码完全适用于eclipse和jar包情况下,根据包名,获取这个包下的所有Clas文件。有不明白的,可以加左边的QQ群讨论。


此文章来自游戏技术网:http://www.youxijishu.com