代码改变世界

ZT:[Java]资源和路径

2015-12-09 11:12  lilooo  阅读(80)  评论(0)    收藏  举报

一、加载资源文件方式总结

from: http://blog.csdn.net/zhoutaohenan/article/details/8467271

在java中,加载文件资源可用如下四种方式:

   1、通过本类的class类的getResource方法

 // 同一包下
URL u0 = ClassGetResourceTest.class.getResource("c1.xml")");
System.out.println(u0.toString());
// 从根寻找资源,需要文件分隔符"/"
URL u = ClassGetResourceTest.class.getResource("/c1.xml");
System.out.println(u.toString());
// 不同包下,相对路径
URL u2 = ClassGetResourceTest.class.getResource("/com/test2/c1.xml");
System.out.println(u2.toString());

2、通过本类的ClassLoad的getResource方法

//同一包中寻找
URL u=ClassLoadGetResourceTest.class.getClassLoader().getResource("c1.xml");
System.out.println(u.toString());
//根路径开始寻找
URL u1=ClassLoadGetResourceTest.class.getClassLoader().getResource("c2.xml");
System.out.println(u1.toString());
//不同包中
URL u2=ClassLoadGetResourceTest.class.getClassLoader().getResource("com/test/c1.xml");
System.out.println(u2.toString());

3、通过ClassLoad的getSystemResource()和getSystemClassLoader().getResource()

 // 同一包下
URL u2 = ClassLoader.getSystemResource("c1.xml");
URL u3 = ClassLoader.getSystemClassLoader().getResource("c1.xml");
System.out.println(u2.toString());
System.out.println(u3.toString());
// 指定包下且不同包
URL u = ClassLoader.getSystemResource("com/test2/c1.xml");
URL u1 = ClassLoader.getSystemClassLoader().getResource(
"com/test2/c1.xml");
System.out.println(u.toString());
System.out.println(u1.toString());
// 从根路径开始
URL u4 = ClassLoader.getSystemResource("c1.xml");
URL u5 = ClassLoader.getSystemClassLoader().getResource("c1.xml");
System.out.println(u4.toString());
System.out.println(u5.toString());

4、通过Thread方式(推荐此种)

 //同一包下
URL u=Thread.currentThread().getContextClassLoader().getResource("c1.xml");
System.out.println(u.toString());
//不同包下
URL u1=Thread.currentThread().getContextClassLoader().getResource("com/test2/c1.xml");
System.out.println(u1.toString());
//根路径下
URL u2=Thread.currentThread().getContextClassLoader().getResource("c2.xml");
System.out.println(u2.toString());

总结: 通过以上四种方式比较可知,除第一种方式(通过本类的class类的getResource)在从根路径和其它包路径下加载资源时,需要加相对路径符"/"外,其它加载资源的路径方式基本是一样的。二、三、四方式在加载同包资源和根路径下资源,指定资源的路径是一样的!

 

二、Java中获取classpath路径下的资源文件

from: http://blog.sina.com.cn/s/blog_9c7605530101gg9d.html

ClassLoader 提供了两个方法用于从装载的类路径中取得资源:

        public URL  getResource (String name);  
        public InputStream  getResourceAsStream (String name);  

       这里name是资源的类路径,它是相对与“/”根路径下的位置。getResource得到的是一个URL对象来定位资源,而getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据。
       但是真正使用的不是ClassLoader的这两个方法,而是Class的 getResource和getResourceAsStream方法,因为Class对象可以从你的类得到(如YourClass.class或 YourClass.getClass()),而ClassLoader则需要再调用一次YourClass.getClassLoader()方法,不过根据JDK文档的说法,Class对象的这两个方法其实是“委托”(delegate)给装载它的ClassLoader来做的,所以只需要使用 Class对象的这两个方法就可以了。

       因此,直接调用  this.getClass().getResourceAsStream(String name) ;获取流,

                静态化方法中则使用ClassLoader.getSystemResourceAsStream (String name) ; 。

      下面是一些得到classpath和当前类的绝对路径的一些方法。你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。

1.this.getClass().getResource("") 
得到的是当前类class文件的URI目录。不包括自己!
如:file:/D:/workspace/jbpmtest3/bin/com/test/

2.this.getClass().getResource("/") 
得到的是当前的classpath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

3.this.getClass() .getClassLoader().getResource("") 
得到的也是当前ClassPath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

4.ClassLoader.getSystemResource("") 
得到的也是当前ClassPath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

5.Thread.currentThread().getContextClassLoader ().getResource("") 
得到的也是当前ClassPath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

6.ServletActionContext.getServletContext().getRealPath(“/”) 
Web应用程序 中,得到Web应用程序的根目录的绝对路径。这样,我们只需要提供相对于Web应用程序根目录的路径,就可以构建出定位资源的绝对路径。
如:file:/D:/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/WebProject


注意点:

1.尽量不要使用相对于System.getProperty("user.dir")当前用户目录的相对路径。这是一颗定时炸弹,随时可能要你的命。

2.尽量使用URI形式的绝对路径资源。它可以很容易的转变为URI,URL,File对象。

3.尽量使用相对classpath的相对路径。不要使用绝对路径。使用上面ClassLoaderUtil类的public static URLgetExtendResource(String relativePath)方法已经能够使用相对于classpath的相对路径定位所有位置的资源。

4.绝对不要使用硬编码的绝对路径。因为,我们完全可以使用ClassLoader类的getResource("")方法得到当前classpath的绝对路径。如果你一定要指定一个绝对路径,那么使用配置文件,也比硬编码要好得多!

获得CLASSPATH之外路径的方法:
URL base = this.getClass().getResource(""); //先获得本类的所在位置,如/home/popeye/testjava/build/classes/net/  
      String path = new File(base.getFile(), "……/……/……/"+name).getCanonicalPath(); //就可以得到/home/popeye/testjava/name

另外,如果从ANT启动程序,this.getClass().getResource("")取出来的比较怪,直接用JAVA命令行调试就可成功。

 

三、META-INF有什么用?

from: http://zhidao.baidu.com/question/288848686.html?fr=iks&word=Specification-Version&ie=gbk

 

META-INF 存在程序入口相关信息, 每个jar 都会有这个文件夹,里面的 MANIFEST文件 记录这些信息

WEB-INF 使用web 项目才会有这个文件夹,普通的 j2se项目 是没有这个文件夹的

我们把MANIFEST中的配置信息进行分类,可以归纳出下面几个大类:
  一. 一般属性
  1. Manifest-Version
  用来定义manifest文件的版本,例如:Manifest-Version: 1.0
  2. Created-By
  声明该文件的生成者,一般该属性是由jar命令行工具生成的,例如:Created-By: Apache Ant 1.5.1
  3. Signature-Version
  定义jar文件的签名版本
  4. Class-Path
  应用程序或者类装载器使用该值来构建内部的类搜索路径
  二. 应用程序相关属性
  1. Main-Class
  定义jar文件的入口类,该类必须是一个可执行的类,一旦定义了该属性即可通过 java -jar x.jar来运行该jar文件。
  三. 小程序(Applet)相关属性
  1. Extendsion-List
  该属性指定了小程序需要的扩展信息列表,列表中的每个名字对应以下的属性
  2. <extension>-Extension-Name
  3. <extension>-Specification-Version
  4. <extension>-Implementation-Version
  5. <extension>-Implementation-Vendor-Id
  5. <extension>-Implementation-URL
  四. 扩展标识属性
  1. Extension-Name
  该属性定义了jar文件的标识,例如Extension-Name: Struts Framework
  五. 包扩展属性
  1. Implementation-Title 定义了扩展实现的标题
  2. Implementation-Version 定义扩展实现的版本
  3. Implementation-Vendor 定义扩展实现的组织
  4. Implementation-Vendor-Id 定义扩展实现的组织的标识
  5. Implementation-URL : 定义该扩展包的下载地址(URL)
  6. Specification-Title 定义扩展规范的标题
  7. Specification-Version 定义扩展规范的版本
  8. Specification-Vendor 声明了维护该规范的组织
  9. Sealed 定义jar文件是否封存,值可以是true或者false (这点我还不是很理解)
  六. 签名相关属性
  签名方面的属性我们可以来参照JavaMail所提供的mail.jar中的一段
  Name: javax/mail/Address.class
  Digest-Algorithms: SHA MD5
  SHA-Digest: AjR7RqnN//cdYGouxbd06mSVfI4=
  MD5-Digest: ZnTIQ2aQAtSNIOWXI1pQpw==
  这段内容定义类签名的类名、计算摘要的算法名以及对应的摘要内容(使用BASE64方法进行编码)