使用Javafx Maven Plugin编译项目后程序找不到资源

After Compiling Project With Javafx Maven Plugin, Program Cant Locate Resources

好吧,我对 javafx 和一般编程还很陌生。我以前从未真正打包过程序,因为我从来不需要 运行 它们在 IDE 之外。我需要打包我的 javafx 程序并且必须使用 maven 来这样做,因为它处理我的所有其他依赖项。

在包含 pom 文件的目录中使用命令 mvn jfx:jar 编译程序后,构建成功并生成我的 jar。通过 WINRar 检查时,其中包含以前位于根目录的 /src/main/resource 文件夹中的所有文件。

然而,当 运行 使用 java -jar (nameofjar).jar 时,它不会启动,而是会产生几个错误,所有错误都与无法找到特定资源有关,尤其是 FXML,在其他资源中。

文件引用

welcome.fxml

public void start(Stage primaryStage) {


    try {
        AnchorPane pane = FXMLLoader.load(MainApp.class.getResource("welcome.fxml"));
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.setTitle("HeelBot Beta "+versionNumber);

        primaryStage.getIcons().add(new Image("Icon.png"));
        primaryStage.setResizable(true);
        primaryStage.show();
    } catch (Exception ex) {
        Logger.getLogger(MainApp.class.getName()).log(Level.SEVERE, null, ex);
    }

defaultProperties.properties

    public class PropertiesManager {
    public static void editProperty(String key, String value) throws IOException {
        // create and load default properties
        Properties defaultProps = new Properties();
        FileInputStream in = new FileInputStream("src/main/resources/defaultProperties.properties");
        defaultProps.load(in);
        in.close();

// create application properties with default
        Properties applicationProps = new Properties(defaultProps);

// now load properties
// from last invocation
        in = new FileInputStream("src/main/resources/appProperties.properties");
        applicationProps.load(in);
        in.close();
//set properties
        applicationProps.setProperty(key,value);
        FileOutputStream out = new FileOutputStream("src/main/resources/appProperties.properties");
        applicationProps.store(out, "---No Comment---");
        out.close();

    }

POM 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.coursecruncher</groupId>
    <artifactId>heelbot</artifactId>
    <version>1.0-SNAPSHOT</version>
<build>
    <plugins>
        <plugin>
            <groupId>com.zenjava</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>8.1.4</version>
            <configuration>
                <mainClass>MainApp</mainClass>
                <verbose>true</verbose>
                <jfxMainAppJarName>heelbot.jar</jfxMainAppJarName>
                <deployDir>${project.basedir}/src/main/resources</deployDir>
                <updateExistingJar>true</updateExistingJar>
                <allPermissions>true</allPermissions>
            </configuration>
        </plugin>

    </plugins>

</build>

    <dependencies>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.48.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.4</version>
        </dependency>
    </dependencies>

</project>

项目结构

├── configure
├── configure.in
├── src
│   ├── main
│   │   ├── java 
│   │   │     ├── CoreController(class)
│   │   │     ├── Login(class)
│   │   │     ├── LoginController(class)
│   │   │     ├── MainApp(class)
│   │   │     └── PropertiesManager(class)
│   │   │        
│   │   ├── resources
│   │   │     ├── appProperties.properties
│   │   │     ├── defaultProperties.properties
│   │   │     ├── welcome.fxml
│   │   │     ├── core.fxml
│   │   │     └── Heelbot.css 

错误

enter code here

java.io.FileNotFoundException: src\main\resources\defaultProperties.properties (
The system cannot find the path specified)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at PropertiesManager.editProperty(PropertiesManager.java:11)
        at LoginController.initialize(LoginController.java:60)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
        at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
        at Main.start(Main.java:53)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication13
(LauncherImpl.java:863)
        at com.sun.javafx.application.PlatformImpl.lambda$runAndWait6(Platfor
mImpl.java:326)
        at com.sun.javafx.application.PlatformImpl.lambda$null4(PlatformImpl.
java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater5(PlatformI
mpl.java:294)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatch
er.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null9(WinApplication.ja
va:191)
        at java.lang.Thread.run(Thread.java:745)
java.io.FileNotFoundException: src\main\resources\defaultProperties.properties (
The system cannot find the path specified)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at PropertiesManager.queryProperty(PropertiesManager.java:34)
        at LoginController.initialize(LoginController.java:106)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
        at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
        at Main.start(Main.java:53)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication13
(LauncherImpl.java:863)
        at com.sun.javafx.application.PlatformImpl.lambda$runAndWait6(Platfor
mImpl.java:326)
        at com.sun.javafx.application.PlatformImpl.lambda$null4(PlatformImpl.
java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater5(PlatformI
mpl.java:294)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatch
er.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null9(WinApplication.ja
va:191)
        at java.lang.Thread.run(Thread.java:745)
Nov 12, 2015 5:12:08 PM Main start
SEVERE: null
javafx.fxml.LoadException:
file:/D:/Programing%20Data/Projects/CourseCruncher/target/jfx/app/heelbot.jar!/w
elcome.fxml

        at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
        at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
        at Main.start(Main.java:53)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication13
(LauncherImpl.java:863)
        at com.sun.javafx.application.PlatformImpl.lambda$runAndWait6(Platfor
mImpl.java:326)
        at com.sun.javafx.application.PlatformImpl.lambda$null4(PlatformImpl.
java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater5(PlatformI
mpl.java:294)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatch
er.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null9(WinApplication.ja
va:191)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
        at java.util.Properties$LineReader.readLine(Properties.java:434)
        at java.util.Properties.load0(Properties.java:353)
        at java.util.Properties.load(Properties.java:341)
        at PropertiesManager.queryProperty(PropertiesManager.java:39)
        at LoginController.initialize(LoginController.java:106)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
        ... 17 more

我怀疑我的 pom 配置可能是导致问题的原因。我不太确定如何正确格式化它,并且尝试了各种组合和教程都无济于事。我得到的最接近的是使用这个 pom

备用 POM 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.courecruncher</groupId>
    <artifactId>heelbot</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>HeelBotBeta1</name>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>2.48.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.4</version>
        </dependency>

    </dependencies>
    <build>
        <defaultGoal>clean package</defaultGoal>
        <plugins>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>unpack-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>unpack-dependencies</goal>
                        </goals>
                        <configuration>
                            <excludeScope>system</excludeScope>
                            <excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
                            <outputDirectory>${project.build.directory}/classes</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <id>package-jar</id>
                        <phase>package</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <executable>${env.JAVA_HOME}/bin/javafxpackager</executable>
                            <arguments>
                                <argument>-createjar</argument>
                                <argument>-nocss2bin</argument>
                                <argument>-appclass</argument>
                                <argument>MainApp</argument>
                                <argument>-srcdir</argument>
                                <argument>${project.build.directory}/classes</argument>
                                <argument>-outdir</argument>
                                <argument>.</argument>
                                <argument>-outdir</argument>
                                <argument>${project.build.directory}</argument>
                                <argument>-outfile</argument>
                                <argument>${project.artifactId}-app</argument>
                                <argument>-v</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

这会导致它找到 fxml 文件,但仍然会抛出属性文件错误,我必须手动将 属性 文件添加到项目目录中。如何让打包后的jar能够定位到自己的资源,而不是去jar外寻找资源?

我是 javafx-maven-plugin 的维护者,偶然发现了这个问题 ;)

问题出在您 "logic" 读取文件的过程中,访问 JAR 中的 属性 文件是通过另一种方式完成的,但这不是所用插件的错误,而是正常的 java-thing(正如抛出的异常所指出的)。要知道 "your current folder" 在哪里,只需打印出 new File(".")

只是通知你 javafx-maven-plugin 配置:没有错

这里是我找到的一些链接,可以向您展示 JAR 文件中属性的简单加载:

Load properties file in JAR?

Load Properties from resources folder within JAR

编辑:请确保对 "current working folder" 有一点了解,调用 java -jar somejar.jar 不同于 java -jar somefolder/somejar.jar,有很大的不同