如何从其他JAR文件加载资源

时间:2014-05-05 07:15:20

标签: java jar classloader

我从其他正在运行的jar中加载资源时遇到麻烦。这是我的设置

resource.jar  # contains resources I want to load
`-res/hwview/file1

engine.jar    # my application which need resources
`-res/hwview/file2

有趣的是,使用下面的代码,我可以加载file2(在我运行的jar中),但不能加载file1

String dir = "res/hwview";
Enumeration<URL> e = getClass().getClassLoader().getResources(dir);
while(e.hasMoreElements()) {
    // prints only file1 from engine.jar 
    // (actually it's in classes directory because I run it from my IDE)
    System.out.println(e.nextElement());
}

[OUTPUT]
/path/to/my/project/SiHwViewUiModel/classes/res/hwview

所以我想也许这个罐子没有被ClassLoader拾取所以我打印了加载的内容

ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
    System.out.println(url.getFile());
}

[OUTPUT]
/path/to/my/project/SiHwViewUiModel/classes/
/path/to/my/project/Resources/deploy/resources.jar
... and other not so important jars

有什么想法吗? 谢谢你的帮助!

4 个答案:

答案 0 :(得分:3)

我找到了解决方案。 getResources()方法和类似方法的问题在于,不能给出目录,只能给出特定文件。这意味着如果我想在整个类路径中搜索特定结构,我需要在基目录中创建 marker 文件。

示例:我想访问my/path目录 - &gt;创建marker.info(名称无关紧要)文件,然后搜索它。

resources.jar
`- my/path/
   |- my/directories
   `- marker.info

resources2.jar
`- my/path/
   |- my/other/directories
   `- marker.info

# search
Enumeration<URL> urls = getClass().getClassLoader().getResources("my/path/marker.info"); 

# print
print(urls);
/path/to/resources.jar!/my/path/marker.info
/path/to/resources2.jar!/my/path/marker.info

答案 1 :(得分:1)

如果JAR文件在类路径上,则不需要做任何特殊操作。资源将被找到。

如果他们不在类路径上,则需要创建URLClassLoader并使用其getResource()方法。

答案 2 :(得分:0)

在Spring中,它可以从类路径中的所有jar文件加载xml文件:

ApplicationContext context = new ClassPathXmlApplicationContext(
        "classpath*:**/applicationContext*.xml");

您可以查看Spring源代码,看看Spring是如何实现的。

答案 3 :(得分:-2)

public final class JarResource
{
private String jarFileName;
private Map<String, Long> hashSizes = new HashMap<String, Long>();
private Map<String, Object> hashJarContents = new HashMap<String, Object>();

public JarResource(String jarFileName) throws Exception
{
    this.jarFileName = jarFileName;
    ZipFile zipFile = new ZipFile(this.jarFileName);

    Enumeration<ZipEntry> e = (Enumeration<ZipEntry>) zipFile.entries();
    while (e.hasMoreElements())
    {
        ZipEntry zipEntry = e.nextElement();
        if(!zipEntry.isDirectory())
        {
            hashSizes.put(getSimpleName(zipEntry.getName()), zipEntry.getSize());
        }
    }
    zipFile.close();

    // extract resources and put them into the hashMap.
    FileInputStream fis = new FileInputStream(jarFileName);
    BufferedInputStream bis = new BufferedInputStream(fis);
    ZipInputStream zis = new ZipInputStream(bis);
    ZipEntry ze = null;

    while ((ze = zis.getNextEntry()) != null)
    {
        if (ze.isDirectory())
        {
            continue;
        }
        else
        {
            long size = (int) ze.getSize();
            // -1 means unknown size.
            if (size == -1)
            {
                size = hashSizes.get(ze.getName());
            }

            byte[] b = new byte[(int) size];
            int rb = 0;
            int chunk = 0;
            while (((int) size - rb) > 0)
            {
                chunk = zis.read(b, rb, (int) size - rb);
                if (chunk == -1)
                {
                    break;
                }
                rb += chunk;
            }

            hashJarContents.put(ze.getName(), b);
        }
    }
    zis.close();
}

public byte[] getResource(String name)
{
    return (byte[]) hashJarContents.get(name);
}

private String getSimpleName(String entryName)
{
    // Remove ".jar" extension
    int index = entryName.indexOf("/");
    String fileNameWithoutExt = entryName.substring(index, entryName.length());

    return fileNameWithoutExt;
}
}

然后使用此类加载资源:

public static void main(String[] args) throws Exception
{
    JarResource jr = new JarResource("/home/mjiang/Downloads/solr-4.8.0/dist/solr-cell-4.8.0-test.jar");
    byte[] resource = jr.getResource("/META-INF/NOTICE.txt");

    InputStream input = new ByteInputStream(resource, resource.length);

    BufferedReader dis = new BufferedReader(new InputStreamReader(input));

    String line = "";
    while((line = dis.readLine()) != null)
    {
        System.out.println(line);
    }

    dis.close();
}