如何在 Java 9 中使用类加载器访问资源
Posted
技术标签:
【中文标题】如何在 Java 9 中使用类加载器访问资源【英文标题】:How to access resource using class loader in Java 9 【发布时间】:2018-07-23 22:41:31 【问题描述】:我在 Eclipse 中有一个 gradle 项目。这是我的项目的结构
我在 scr/main/resources/css
中有 css 资源 styleclass.css
。首先,我尝试使用
scene.getStylesheets().add("css/styleclass.css");
但是我收到了警告 resource not found.
我也通过删除 module-info.java
文件进行了尝试。但结果是一样的。
然后我用
试了一下String urlString = ComboBoxStyling.class.getClassLoader().getResource("css/styleclass.css").toExternalForm();
问题是,如果我删除 moduele-info.java
并应用样式表,这条线就可以工作。但是module-info.java
我得到空指针异常。
我知道的不多,但至少我知道类加载器在 Java 9 中发生了变化。那么我怎样才能在 Java 9 中做同样的事情。我的 module-info.java
文件包含以下内容
module pk.training.basit
exports pk.training.basit;
requires transitive javafx.controls;
感谢和问候
巴斯特·马哈茂德·艾哈迈德
【问题讨论】:
资源已被封装,因此无法通过 ClassLoader API 找到。我假设 ComboBoxStyling.class..getResource("/css/styleclass.css") 将起作用 - 请注意前导斜杠,以便相对于模块的根位置找到它,而不是相对于 ComboBoxStyling.class 在这种情况下。 是的,这是工作:) @Alan Bateman 发表您的答案,以便我接受 ***.com/questions/46861589/… 【参考方案1】:来自ClassLoader.getResource
JavaDoc:
命名模块中的资源受 Module.getResourceAsStream 指定的封装规则的约束。另外,除了资源名称以“.class”结尾的特殊情况外,该方法只会在无条件打开包的情况下查找命名模块包中的资源(即使该方法的调用者在同一模块作为资源)。
所以,要解决你的问题,你应该打开包css
:
module pk.training.basit
exports pk.training.basit;
requires transitive javafx.controls;
opens css;
【讨论】:
最初的问题似乎是代码试图找到自己的资源。 ClassLoader API 是错误的 API。将代码更改为在模块中的类上调用 getResource 后,它应该可以正常工作,无需打开任何包。 @AlanBateman 我只是回答了 OP 的要求。如果他有 200 个getClassLoader().getResource()
的位置怎么办?所以他可以只添加一行代码,而不是改变那 200 个地方。【参考方案2】:
您应该将您的 css 与使用它的类放在同一个包中,然后使用 Class.getResource 使用相对路径访问它。
src/main/java:
pk.training.basit
ComboBoxStyling.java
src/main/resources:
pk.training.basit
ComboBoxStyling.css
然后在源码中:
scene.getStylesheets().add(
ComboBoxStyling.class.getResource("ComboBoxStyling.css").toExternalForm());
个人觉得最好还是把css和class放在同一个目录下,然后配置gradle这样就可以占用src/main目录下的资源了。它允许拥有类似于其他 GUI 产品 (Angular) 的架构,它将屏幕的所有资源(包括源代码)放在同一目录中,例如 FXML 文件,如果你有的话。
【讨论】:
以上是关于如何在 Java 9 中使用类加载器访问资源的主要内容,如果未能解决你的问题,请参考以下文章