如何使用 Gradle 访问 Java 项目中的资源?

Posted

技术标签:

【中文标题】如何使用 Gradle 访问 Java 项目中的资源?【英文标题】:How to access a resource in Java project using Gradle? 【发布时间】:2016-01-23 12:16:05 【问题描述】:

我有一个使用 Gradle 文件构建的 javafx 项目,我在 Intellij 中编写所有内容。在其中,我使用 javafx.scene.media.Media 和 javafx.scene.media.MediaPlayer 播放一些音乐。

public SoundPlayer(String filename) 
    String soundLocation = "\\src\\main\\resources\\sound\\" + fileName;
    String absolute = new File("").getAbsolutePath() + soundLocation;
    System.out.println(absolute);
    Media soundMedia = new Media(new File(absolute).toURI().toString());
    mediaPlayer = new MediaPlayer(soundMedia);

我一直在工作的项目目录是:

src/

|---主要/

|---|---java/

|---|---|---sound.SoundPlayer

|---|---资源/

|---|---|---声音/

|---|---|---|---click.mp3

|---|---|---|---bgm.mp3

但是,当我去编译并将其转换为 jar 文件时,Gradle 将目录更改为这个(在 jar 文件中,顶层):

声音/

|---SoundPlayer.class

|---click.mp3

|---bgm.mp3

这使它引发了媒体异常:媒体不可用。我尝试将文件更改为以下两种:

Media soundMedia = new Media(new File("sound\\" + fileName).toURI().toString());

Media soundMedia = new Media(new File(fileName).toURI().toString());

...但我总是遇到同样的异常。怎么回事?

【问题讨论】:

你也可以分享你的gradle构建文件 【参考方案1】:

Gradle 所做的一切完全在意料之中。 src/main/javasrc/main/resources 目录分别存储代码和资源。 resources 文件夹包含所有非 java 代码,如图像、声音等。

创建jar文件时,会原样复制resources目录的内容(保持包结构)。请注意,click.mp3bgm.mp3sound 包的成员。

因此,当您要加载资源时,(通常)不应该使用文件路径来完成。而是使用包结构来做到这一点。在这里,由于声音和SoundPlayer具有相同的包,即sound,您可以使用SoundPlayer类来加载资源,如下所示:

public SoundPlayer(String filename) 
    URL resource = SoundPlayer.class.getResource(filename);
    Media soundMedia = new Media(resource.toExternalForm());
    mediaPlayer = new MediaPlayer(soundMedia);

来自 Javadocs

公共字符串 toExternalForm() 构造此 URL 的字符串表示形式。该字符串是通过为此对象调用流协议处理程序的 toExternalForm 方法创建的。

本质上,toExternalForm() 函数为给定资源创建适当的 URL。

这是一个完整的例子。

// build.gradle
apply plugin: 'java'
apply plugin: 'application'

sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'


mainClassName = 'sound.Main'

repositories 
    mavenCentral()


dependencies 
    testCompile group: 'junit', name: 'junit', version: '4.10'


jar  manifest  attributes 'Main-Class': 'sound.Main'   

和修改后的 SoundPlayer

//sound.SoundPlayer
package sound;

import java.net.URL;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

public class SoundPlayer 

    private MediaPlayer mediaPlayer;

    public SoundPlayer(String filename) 
        URL resource = SoundPlayer.class.getResource(filename);
        Media soundMedia = new Media(resource.toExternalForm());
        mediaPlayer = new MediaPlayer(soundMedia);
    

    public void play()
        mediaPlayer.play();
    

以及使用 SoundPlayer 的 Main 类

// sound.Main
// This class does not actually create a JavaFX UI. Instead, it is
// only creating a JavaFX application to use Media
package sound;

import javafx.application.Application;
import javafx.stage.Stage;

/**
 *
 * @author aga53
 */
public class Main extends Application

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) 
        launch(args);
    

    @Override
    public void start(Stage primaryStage) throws Exception 
        SoundPlayer s = new SoundPlayer("test.mp3");
        System.out.println("Hello World");
        s.play();
    


【讨论】:

以上是关于如何使用 Gradle 访问 Java 项目中的资源?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 build.gradle 文件中设置属性以在 Java 中访问该属性

如何使用 Gradle 中的本地 JUnit Jar 而不是 Maven Central?

如何在 Java 9 中使用类加载器访问资源

使用 Gradle 构建 Java 项目

使用 Gradle 构建 Java 项目

Spring Boot 项目中的 Gradle 无法识别路径中的 Java jdk