您的位置:首页 > 编程语言 > Java开发

Java运行命令方式与classpath和getResource之间的关系

2015-01-07 22:32 323 查看

Java的两种运行方式

先介绍Java的两种运行方式:

1.Java -jar ***.jar

这种方式必须在jar包中的MANIFEST.MF文件中指定所有运行该jar所需的所有依赖包和资源,例如:Main-Class,Class-Path等。
当使用-jar的方式运行时,会忽略掉参数-classpath和环境变量中classpath,所以在这种方式下通过这两种方式来指定classpath是没有效果的,只有MANIFEST.MF文件中Class-Path才有效。

2.Java -classpath [jar包路径;其它需要加装的路径] com.***.***.MainClass
使用这种方式运行Java的时候,会在classpath(可以通过命令行中-classpath指定,也可以通过设置环境变量classpath指定)路径下寻找命令行中指定的类(main函数所在类)进行启动。

classpath的路径组织方式

在classpath中可以指定具体的jar包路径和在程序中需要用到的资源目录路径。例如:classpath=D:\ClassLoaderResourceTest.jar;D:\test2;D:\test。如果需要指定多个jar包,可以使用统配符,例如:D:\JarPackage\*,这样就可以加载所有需要的jar包了(当使用这种方式的时候,*并不匹配除了jar包文件外的其它东西,例如:D:\JarPackage\这个目录下有另外的资源文件,则D:\JarPackage\*这个方式只会加载该目录下的jar包,其它资源文件是无法加载进来的)。
当给classpath指定jar包或者目录路径的时候,相当于把jar包和目录路径都挂载到了classpath的根目录下,从而形成其classpath内部的目录结构。从表象上来看,跟Linux系统的挂载类似。

举个例子:

设置classpath为D:\ClassLoaderResourceTest.jar;D:\test2;D:\test,其中ClassLoaderResourceTest.jar目录结构如下:



D:\test2的目录下面只有一个f.txt文件,D:\test目录下面有一个d.txt文件和one目录,one目录下有一个e.txt文件。
所以这个classpath的目录结构如下:



当Java运行时从classpath中获取资源的时候,将遵循这个目录结构来获取所需要的资源,所以当从classpath获取不到需要的资源的时候,需要好好理解一下classpath的目录组织结构。

classpath指定jar包所在路径,却加载不到类:
在通过classpath指定jar包的时候,会有人只指定路径,而没有指定具体jar包,从而导致类加载不到。其实表象的原理是和Linux的挂载完全一样的,当指定一个目录挂载的时候,该目录下的jar包只是被当做了一个普通的文件,而该文件内容对于JVM来说是未知的,所以加载类的时候,找不到包里面的class文件。当指定具体jar包的时候,就跟在Linux上面挂载一个镜像文件一样,会展开里面的目录结构,相当于把包里面的整个目录结构都挂载进来了,就如同上面表格一样,所以ClassLoader就能按照类名加载到所需要的class文件了。

getResource的使用介绍

这边介绍两种getResource的区别和使用,在Class类中和ClassLoader类中分别存在一个getResource方法,这两个方法都是从classpath中寻找指定资源并获取资源的绝对路径,供后续加载资源用。

区别在于从classpath中加载资源时候的路径不一样。

Class类中的getResource方法,存在相对路径和绝对路径两种。

相对路径:当使用相对路径时,将从该类所在的路径下面开始定位资源,也就是相对于该类所在位置的目录。例如:ClassLoaderResourceTest.class.getResource("a.txt"),从上面的classpath目录组织结构可以看出,ClassLoaderResourceTest类与a.txt处在同个目录下;如果要取b.txt资源,则ClassLoaderResourceTest.class.getResource("conf/b.txt")。如果需要去位于该类所在目录的父目录的资源,无法跟Linux文件系统一样,通过../来定位资源,而是需要使用绝对路径的方式来定位。
绝对路径:就是在classpath的根目录下定位文件,和Linux一样,classpath的目录组织结构也是通过/来表示根目录。所以如果需要定位c.txt文件,就可以通过ClassLoaderResourceTest.class.getResource("/c.txt")来定位。
通过相对路径和绝对路径的配合,可以取到classpath中的所有资源。

ClassLoader中的getResource方法,只存在相对路径。

为什么这个方法会只有一个相对路径的方式呢,原因就在于它的起始路径在classpath的根目录下,所以只需要使用相对路径,就能取到classpath下的所有资源了。例如:ClassLoaderResourceTest.class.getClassLoader().getResource("c.txt"),ClassLoaderResourceTest.class.getClassLoader()
.getResource("com/cyc/classloader/test/a.txt")。

示例

如下示例演示了classpath的目录组织结构和getResource的两种不同使用:
package com.cyc.classloader.test;

public class ClassLoaderResourceTest {

public static void main(String[] args) {

//获取与ClassLoaderResourceTest同目录下资源。
//输出结果:jar:file:/D:/ClassLoaderResourceTest.jar!/com/cyc/classloader/test/a.txt
System.out.println(ClassLoaderResourceTest.class.getResource("a.txt"));
//获取与ClassLoaderResourceTest同目录下资源。
//输出结果:jar:file:/D:/ClassLoaderResourceTest.jar!/com/cyc/classloader/test/conf/b.txt
System.out.println(ClassLoaderResourceTest.class.getResource("conf/b.txt"));
//获取与ClassLoaderResourceTest父目录下资源,使用相对路径无法获取,不支持../
//输出结果:null
System.out.println(ClassLoaderResourceTest.class.getResource("../g.txt"));
//与ClassLoaderResourceTest类不处于同目录,路径不对
//输出结果:null
System.out.println(ClassLoaderResourceTest.class.getResource("c.txt"));
//使用绝对路径,从根目录下获取
//输出结果:jar:file:/D:/ClassLoaderResourceTest.jar!/c.txt
System.out.println(ClassLoaderResourceTest.class.getResource("/c.txt"));
//使用绝对路径,获取根目录下的子目录文件,该目录是属于test,不属于jar包
//输出结果:file:/D:/test/one/e.txt
System.out.println(ClassLoaderResourceTest.class.getResource("/one/e.txt"));
//使用相对路径,获取jar包中的文件,该文件处于classpath的根目录下
//输出结果:jar:file:/D:/ClassLoader
99ce
ResourceTest.jar!/c.txt
System.out.println(ClassLoaderResourceTest.class.getClassLoader().getResource("c.txt"));
//使用相对路径,获取test目录中的文件,该文件处于classpath的根目录下
//输出结果:file:/D:/test/d.txt
System.out.println(ClassLoaderResourceTest.class.getClassLoader().getResource("d.txt"));
//使用绝对路径,但是ClassLoader中的方法不支持绝对路径。
//输出结果:null
System.out.println(ClassLoaderResourceTest.class.getClassLoader().getResource("/"));
}
}


运行命令如下:
java -classpath D:\ClassLoaderResourceTest.jar;D:\test2;D:\test com.cyc.classloader.test.ClassLoaderResourceTest


输出结果如下:
jar:file:/D:/ClassLoaderResourceTest.jar!/com/cyc/classloader/test/a.txt
jar:file:/D:/ClassLoaderResourceTest.jar!/com/cyc/classloader/test/conf/b.txt
null
null
jar:file:/D:/ClassLoaderResourceTest.jar!/c.txt
file:/D:/test/one/e.txt
jar:file:/D:/ClassLoaderResourceTest.jar!/c.txt
file:/D:/test/d.txt
null
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐