如何使用 Maven 和 NetBeans 将应用程序打包到 JPMS 模块中?

How to package an application into JPMS modules using Maven and NetBeans?

我的目标是使用 jlink 将应用程序打包到与自定义 JRE 捆绑在一起的模块化运行时映像中。我的应用程序是一个简单的 "hello world" Java 标准版应用程序,依赖于 Guava。我用的是 JDK 11.

基本上我尝试重现 this tutorial by Baeldung, but with NetBeans, Maven to manage the dependencies and the Maven Compiler Plugin 版本 3.8.1 以使用模块系统构建。

目录结构:

模块-info.java文件:

module TestwithJLink {
    requires guava;
    exports net.clementlevallois.testwithjlink;
}

Controller.java:

package net.clementlevallois.testwithjlink;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;

public class Controller {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Multiset<String> test = HashMultiset.create();
       test.add("hello");
       test.add("world");
        System.out.println("test: "+ test.toString());
    }

}

pom.xml:

<?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>net.clementlevallois</groupId>
    <artifactId>TestwithJLink</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <id>compile</id>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
</project>

但它创建编译的 类,没有 jar 或模块。所以我不能更进一步(用jdeps分析jar的模块,然后用jlink)。我一定是遗漏了一些明显的东西,但是什么?

如果要创建 JAR 文件,请在终端中转到包含 pom.xml 的根文件夹并键入:

mvn package

这将在目标文件夹中创建一个 JAR。 现在将您在终端中的路径更改为目标文件夹和 运行 JAR 文件,使用:

java -jar {file-name-version}.jar

终于明白了。场景:

  • 使用 NetBeans,您的依赖项由 Maven 处理
  • 你的应用有一个模块-info.java声明
  • 你的依赖也有一个 module-info.java 声明。

您想以尊重模块化系统的方式打包您的应用程序。所以:

  • 在您的 pom 中列出这 3 个 Maven 插件(见下文)。注意插件的版本号!特别是,maven-dependency-plugin 中的 <goal>resolve</goal> 确保您的依赖项与它们的模块 打包在一起 - info.java 文件,否则情况并非如此! (see here).
  • 编译完成后,将应用程序的 jar 移动到 lib 文件夹中,所有依赖项的 jar 都已位于该文件夹中。

您可以直接使用 NetBeans 中的 运行 图标 运行 此应用程序,或者:

  • 从您的 lib 文件夹的父文件夹,运行:java --module-path lib --module NameOfYourModule

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>net.clementlevallois</groupId>
    <artifactId>TestwithJLink</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>net.clementlevallois</groupId>
            <artifactId>utils</artifactId>
            <version>1.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>install</phase>
                        <goals>
                            <goal>resolve</goal>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>

                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.2</version>                
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>net.clementlevallois.testwithjlink.Controller</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <id>compile</id>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
</project>