iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java 正确地从类路径中获取资源
  • 130
分享到

Java 正确地从类路径中获取资源

2024-04-02 19:04:59 130人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录Java 可通过以下几种方法来访问资源:Class.getResource 与 ClassLoader.getResource 的区别测试代码打包为 jar 包后的变化错误与陷阱

Java 可通过以下几种方法来访问资源:

  • Class 的 getResource 方法
  • ClassLoader 的 getResource 方法
  • ClassLoader 的 getSystemResource 静态方法

在使用中,Class 可通过直接引用类的 class 属性而获得,或是通过实例的 getClass() 方法来获得。获取 ClassLoader 的方式则比较多,常见以下几种:

  • 调用 Class 的 getClassLoader 方法,如:getClass().getClassLoader()
  • 由当前线程获取 ClassLoader:Thread.currentThread().getContextClassLoader()
  • 获取系统 ClassLoader: ClassLoader.getSystemClassLoader()

不过,若是对 Java 的 ClassLoader 概念不太了解,最好还是尽量避免使用它。

Class.getResource 与 ClassLoader.getResource 的区别

这两种方式,都接受一个字符串形式的路径表达式,即资源名,并返回找到的资源的 URL。两种方式都可用来定位资源,在网络上流传的文章中,两者都是常见的。实际上,Class 的 getResource 方法也调用了 ClassLoader 的 getResource 方法,但两者有着很大的不同,不了解这两种方法的区别,就容易造成隐患。隐患经常比编写时就出错要可怕得多,因为它在一定场合下是正常的,不容易被发现。

两者最大的区别,是从哪里开始寻找资源。ClassLoader 并不关心当前类的包名路径,它永远以 classpath 为基点来定位资源。而 Class.getResource 则不同,如果资源名是绝对路径(以"/"开头),它会将开头的"/"去除,然后调用 ClassLoader 的 getResource 方法来寻找资源;如果资源名是相对路径,它会在当前的包路径下面寻找资源。

举例来说,假设我们有一个类:test.App (包名为 test),并且在 test 包下有一个与类名同名的 js 文件,名为 App.js。如果用 ClassLoader 来获取这个 js 文件,应该这样写:


App.class.getClassLoader().getResource("test/App.js");

如果用 Class 的 getResource 方法,则有两种写法:

  • 使用相对路径:

App.class.getResource("App.js");
  • 使用绝对路径:

App.class.getResource("/test/App.js");

从上面的例子,可以看出两者之间巨大的区别。有些人从网络上复制类似的代码,看看不能正确运行,就开始尝试在资源名前加上 "/",或是去掉开头的 "/",试成功了,便算完工,这绝非正道。

Class 与 ClassLoader 的 getResource 方法还有其它一些不同,对 Class 的 getResource 方法来说,若传入的是相对路径,它还会尝试做包名与路径名的转换。查看 Class.getResource 方法的源码,可以看到它首先对资源名调用了 resolveName 方法,然后再调用 ClassLoader 的 getResource 方法来完成资源的定位。

测试代码

作为演示,我写了以下代码来展示 Class 与 ClassLoader 的 getResource 方法的输出:



package test;

import java.net.URL;
import java.util.Enumeration;


public class ClassResourceTest {
    Class<ClassResourceTest> cls = ClassResourceTest.class;
    ClassLoader ldr = cls.getClassLoader(); // Thread.currentThread().getContextClassLoader()

    public static void println(Object s) {
        System.out.println(s);
    }

    void showResource(String name) {
        println("## Test resource for: “" + name + "” ##");
        println(String.fORMat("ClassLoader#getResource(\"%s\")=%s", name, ldr.getResource(name)));
        println(String.format("Class#getResource(\"%s\")=%s", name, cls.getResource(name)));
    }
    public final void testForResource() throws Exception {
        showResource("");
        showResource("/");
        showResource(cls.getSimpleName() + ".class");
        String n = cls.getName().replace('.', '/') + ".class";
        showResource(n);
        showResource("/" + n);
        showResource("java/lang/Object.class");
        showResource("/java/lang/Object.class");
    }

    public static void main(String[] args) throws Exception {
        println("java.class.path: " + System.getProperty("java.class.path"));
        println("user.dir: " + System.getProperty("user.dir"));
        println("");
        ClassResourceTest t = new ClassResourceTest();
        t.testForResource();
    }
}

编译上述代码,看看不同资源路径的输出结果。

打包为 Jar 包后的变化

现在,将上述代码编译后的结果打包成 Jar 文件,假设是 test.jar ,然后从这个 jar 包中运行上述代码,再看看输出结果,比较下与上面的输出有什么变化:


java -classpath test.jar test.ClassResourceTest

值得注意的几点:

  • Class.getResource("") 还有其它一些输出,结果是 jar:file:/some_path/test.jar!/some_path,而在打包为 Jar 之前,它们的输出形式是 file:/some_path...;
  • Class.getResource("/") 为 null,而在打包之前,该输出是 ClassResourceTest 的类路径;
  • ClassLoader.getResource("") 为 null,而在打包之前,该输出是 ClassResourceTest 的类路径;
  • 调用 ClassLoader.getResource 方法时,若资源名为绝对路径,不管是否打包,其输出结果为 null,至少在我这里是这样。

错误与陷阱

  • 使用 Class.getResource("/") 或 ClassLoader.getResource("") 来当作类路径的根。

这是一种常见的错误,并在网络上广为流传。它们在打包成 Jar 包后,其结果会发生变化。

  • 获得 getResource 方法的输出后,简单地对结果调用 getFile 或 getPath,并把它当作文件路径来处理。

资源有可能以文件和目录的形式位于类路径之中,但也可能打包进了 Jar 包或 Zip 包,你不能假设你的代码不会被打包。

  • 将绝对路径传给 ClassLoader 的 getResource 方法。

网络上有人说,对于 ClassLoader 的 getResource 方法来说,资源名是否以 "/" 开头是一样的,然而,在我这里,ClassLoader 的 getResource 方法并不接受绝对路径,其输出结果为 null。

正确使用 getResource 方法

  • 避免使用 Class.getResource("/") 或 ClassLoader.getResource("")。你应该传入一个确切的资源名,然后对输出结果作计算。比如,如果你确实想获取当前类是从哪个类路径起点上执行的,以前面提到的 test.App 来说,可以调用 App.class.getResource(App.class.getSimpleName() + ".class")。如果所得结果不是 jar 协议的URL,说明 class 文件没有打包,将所得结果去除尾部的 "test/App.class",即可获得 test.App 的类路径的起点;如果结果是 jar 协议的 URL,去除尾部的 "!/test/App.class",和前面的 "jar:",即是 test.App 所在的 jar 文件的 url。
  • 如果要定位与某个类同一个包的资源,尽量使用那个类的getResource方法并使用相对路径。如前文所述,要获取与 test.App.class 同一个包下的 App.js 文件,应使用  App.class.getResource("App.js") 。当然,事无绝对,用 ClassLoader.getResource("test/App.js") 也可以,这取决于你所面对的问题是什么。
  • 如果对 ClassLoader 不太了解,那就尽量使用 Class 的 getResource 方法。
  • 如果不理解或无法确定该传给 Class.getResource 方法的相对路径,那就以类路径的顶层包路径为参考起点,总是传给它以 "/" 开头的路径吧。
  • 不要假设你的调试环境就是最后的运行环境。你的代码可能不打包,也可能打包,你得考虑这些情况,不要埋坑。

getResources: 枚举资源

Java 的 CLASSPATH 是一个路径列表,因此,有可能在多个类路径中出现同样的资源名。如果要列举它们,可以使用 ClassLoader 的 getResources 方法。

下面的代码可以枚举所有的 "META-INF/MANIFEST.MF",你还可以观察到在类路径中哪些 jar 文件包含有该资源:


import java.net.URL;
import java.util.Enumeration;
public class Test {
    public static void main(String[] args) throws Exception {
        ClassLoader ldr = Test.class.getClassLoader();
        System.out.println("## Test for getResources(‘META-INF/MANIFEST.MF') ##");
        Enumeration<URL> urls = ldr.getResources("META-INF/MANIFEST.MF");
        while(urls.hasMoreElements())
            System.out.println(urls.nextElement());
    }
}

实例

下面的代码演示了如何正确获取代码的类路径起点:



package test;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class AppDirTest {
	Classcls = AppDirTest.class;
	URL codeLocation = getCodeLocation();

	
	public URL getCodeLocation() {
		if (codeLocation != null)
			return codeLocation;
		// Get code location using the CodeSource
		codeLocation = cls.getProtectionDomain().getCodeSource().getLocation();
		if (codeLocation != null)
			return codeLocation;
		// If CodeSource didn't work, use {@link } Class.getResource instead.
		URL r = cls.getResource("");
		synchronized (r) {
			String s = r.toString();
			Pattern jar_re = Pattern.compile("jar:\\s?(.*)!/.*");
			Matcher m = jar_re.matcher(s);
			if (m.find()) { // the code is run from a jar file.
				s = m.group(1);
			} else {
				String p = cls.getPackage().getName().replace('.', '/');
				s = s.substring(0, s.lastIndexOf(p));
			}
			try {
				codeLocation = new URL(s);
			} catch (MalformedURLException e) {
				throw new RuntimeException(e);
			}
		}
		return codeLocation;
	}

	
	public String getAppDir() {
		File f = new File(getCodeLocation().getPath());
		return f.isFile() ? f.getParent() : f.getPath();
	}

	public static void main(String[] args) {
		AppDirTest t = new AppDirTest();
		System.out.println("code location: " + t.getCodeLocation());
		System.out.println("app dir: " + t.getAppDir());
	}

}

以上就是Java 正确地从类路径中获取资源的详细内容,更多关于Java 从类路径中获取资源的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java 正确地从类路径中获取资源

本文链接: https://www.lsjlt.com/news/126481.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java 正确地从类路径中获取资源
    目录Java 可通过以下几种方法来访问资源:Class.getResource 与 ClassLoader.getResource 的区别测试代码打包为 Jar 包后的变化错误与陷阱...
    99+
    2024-04-02
  • Java正确地从类路径中获取资源的示例分析
    这篇文章给大家分享的是有关Java正确地从类路径中获取资源的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Java 可通过以下几种方法来访问资源:Class 的 getResource 方法ClassLo...
    99+
    2023-06-15
  • Java项目中classpath类路径如何获取
    今天小编给大家分享一下Java项目中classpath类路径如何获取的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、简介c...
    99+
    2023-07-05
  • Java读取resources下的文件及资源路径
    Java读取resources下的文件及资源路径 在Java开发中,经常需要读取项目中resources目录下的文件或获取资源路径。本文将介绍如何在Java中读取resources下的文件,并提供相关...
    99+
    2023-08-31
    java 前端 数据库
  • 如何在Java中正确配置类路径和索引?
    在Java应用程序中,类路径和索引是非常重要的概念。正确配置类路径和索引可以确保应用程序能够正确地加载所需的类和资源文件。这篇文章将介绍如何在Java中正确配置类路径和索引。 一、类路径 类路径是Java虚拟机(JVM)用来搜索类文件和资源...
    99+
    2023-09-01
    load path 索引
  • java中如何获取class路径
    这篇文章主要讲解了“java中如何获取class路径”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“java中如何获取class路径”吧!可以在servlet的init方法里String pa...
    99+
    2023-06-03
  • Java中怎么获取路径的绝对路径和相对路径
    今天小编给大家分享一下Java中怎么获取路径的绝对路径和相对路径的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前言:在纯 J...
    99+
    2023-06-29
  • Java IDE中如何正确设置NumPy路径?
    NumPy是Python语言中的一种科学计算库,提供了高效的多维数组对象以及各种派生对象(如掩码数组和矩阵)。它是Python科学计算的核心库之一,被广泛应用于数据分析、科学计算、机器学习等领域。在Java开发中,很多时候需要使用Java...
    99+
    2023-10-23
    ide path numy
  • 如何在Java IDE中正确加载路径?
    Java是一门广泛应用于开发各种应用程序的编程语言。在开发Java程序时,我们通常会使用集成开发环境(IDE),例如Eclipse或IntelliJ IDEA。在IDE中正确加载路径是非常重要的,因为它涉及到我们的程序是否能够正确地访问所需...
    99+
    2023-07-23
    ide path load
  • JAVA文件中如何获取路径
    这篇文章主要介绍了JAVA文件中如何获取路径,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1. 基本概念的理解`绝对路径`:你应用上的文件或目录在硬盘上真正的路径,如:URL...
    99+
    2023-05-30
    java
  • java中怎么获取当前路径
    在Java中,可以使用`System.getProperty("user.dir")`来获取当前工作目录的路径。示例代码如下:```...
    99+
    2023-08-18
    java
  • 如何在Java中正确处理LeetCode中的路径?
    Java是一种广泛使用的编程语言,常用于开发Web应用程序、移动应用程序和桌面应用程序等。在Java编程中,很多程序员都会遇到LeetCode上的路径问题。这些问题包括如何正确处理文件路径、URL路径和相对路径等。在本文中,我们将探讨如何在...
    99+
    2023-09-21
    path leetcode 响应
  • java如何获取当前项目的路径地址
    在Java中,可以使用以下代码获取当前项目的路径地址:1. 使用`System.getProperty("user.dir")`方法...
    99+
    2023-09-13
    java
  • Go语言中如何正确地处理路径数据类型的响应?
    Go语言作为一种高性能的编程语言,在处理路径数据类型的响应时有其独特的方式。正确地处理路径数据类型是编写高质量Go应用程序的重要组成部分。在本文中,我们将探讨如何使用Go语言正确地处理路径数据类型的响应。 一、路径数据类型 在Go语言中,路...
    99+
    2023-09-25
    响应 path 数据类型
  • Java项目中获取路径的绝对路径问题和相对路径问题
    目录1.目录结构2.class.getResource(Stringname)3.class.getClassLoader().getResource(Stringname)3.1区...
    99+
    2024-04-02
  • Java读取resources中资源文件路径以及jar中文件无法读取的解决
    目录Java读取resources中资源文件路径以及jar中文件无法读取的解决问题描述前言1、本地运行读取资源文件2、读取jar包中的文件信息聊聊Java项目读取resources资...
    99+
    2023-05-20
    Java读取resources Java读取resources文件路径 jar文件无法读取
  • Java读取resources中资源文件路径以及jar中文件无法读取如何解决
    今天小编给大家分享的是Java读取resources中资源文件路径以及jar中文件无法读取如何解决,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。Java读取resources中资源文...
    99+
    2023-07-06
  • 如何在Java IDE中检查NumPy的路径是否正确?
    在Java开发中,我们常常需要使用NumPy这个强大的数学库。然而,有时候我们会遇到一个问题,那就是如何在Java IDE中检查NumPy的路径是否正确。在本文中,我们将为您提供一些解决方案,以确保您在使用NumPy时不会遇到任何问题。 首...
    99+
    2023-10-23
    ide path numy
  • -classpath及路径如何正确的在Java项目中使用
    这期内容当中小编将会给大家带来有关-classpath及路径如何正确的在Java项目中使用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。javac -classpath的使用:javac:如果当前你要编译...
    99+
    2023-05-31
    java classpath 路径
  • 如何在Java应用程序中正确配置日志路径?
    作为一名Java程序员,日志是我们不可避免的一部分。正确的配置日志路径可以帮助我们更好地追踪问题和调试代码。在本文中,我们将探讨如何在Java应用程序中正确配置日志路径。 在Java中,我们通常使用Log4j或Logback来记录日志。这两...
    99+
    2023-10-17
    日志 教程 path
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作