2014-09-21 17:50:46

URLClassLoader 加载外部jar获取 JarFile(HTTP)问题(JarURLConnection)

当通过URLClassLoader去load一个外部的jar(HTTP)后获取这个jar实体对象会有一点小问题。正常情况下:
URL u = getClass().getProtectionDomain().getCodeSource().getLocation();
即可获取到当前的jar路径,因为是URLClassLoader所以这里拿到的URI可能是HTTP协议。即:http://xxx.com/xxx.jar。这个时候如果:
JarURLConnection juc = (JarURLConnection) new URL(name).openConnection();
无法从HttpURLConnection转为JarURLConnection:
java.lang.ClassCastException: sun.net.www.protocol.http.HttpURLConnection cannot be cast to java.net.JarURLConnection

API中给出的Demo:

一个JAR实体:
jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class
一个JAR文件
jar:http://www.foo.com/bar/baz.jar!/
一个JAR目录
jar:http://www.foo.com/bar/baz.jar!/COM/foo/
!/ 作为引用分割

Class JarURLConnection

这样写似乎就可以了:

//URL a = getClass().getResource("/" + getClass().getName().replace('.', '/') + ".class");
URL a = getClass().getResource("");
JarURLConnection juc = (JarURLConnection) a.openConnection();
JarFile jf = juc.getJarFile();

测试代码:

package com.test.hello;
import java.io.File;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class JarTest {
	public void getAllClass(File f, Path path, List<String> ls){
		if(f.isDirectory()){
			File[] files = f.listFiles();
			for (int i = 0; i < files.length; i++) {
				getAllClass(files[i],path,ls);
			}
		}else{
			if(f.toString().endsWith(".class")){
				String classPath = f.toString().replaceFirst(path.toString(), "");
				classPath = classPath.startsWith("/")?classPath.replaceFirst("/", "").replaceAll("/", "."):classPath;
				ls.add(classPath.substring(0,classPath.length()-".class".length()));
			}
		}
	}
	public void getClassPath(List<String> ls){
        try {
        	URL u = getClass().getProtectionDomain().getCodeSource().getLocation();
        	if(!"http".equalsIgnoreCase(u.toURI().getScheme()) && new File(u.toURI()).isDirectory()){
        		File f = new File(u.toURI());
        		getAllClass(f,f.toPath(),ls);
        	}else{
        		URL a = getClass().getResource("");
        		JarURLConnection juc = (JarURLConnection) a.openConnection();
        		JarFile jf = juc.getJarFile();
                Enumeration<JarEntry> je = jf.entries();
                while (je.hasMoreElements()) {
                    JarEntry jar = je.nextElement();
                    if(jar.getName().endsWith(".class")){
                    	String classPath = jar.getName().replaceAll("/", ".");
                    	ls.add(classPath.substring(0,classPath.length()-".class".length()));
                    }
                }
        	}
        } catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		List<String> ls = new ArrayList<String>();
		new JarTest().getClassPath(ls);
		for(String s:ls){
			System.out.println(s);
		}
	}
}
发表回复