使用jlink工具模块化Java应用,结合Docker优化容器镜像(下)

使用jlink工具模块化Java应用,结合Docker优化容器镜像(上) 

使用jlink工具模块化Java应用,结合Docker优化容器镜像(中)

依赖统一管理

当项目中的依赖越来越多时,对模块的管理会越发的复杂,容易出错。这里使用maven-dependency-plugin插件对依赖做统一的管理,减少工作量,避免不必要的模块管理工作。注意:这个插件需要放在第一个插件的位置,避免将其它插件生成的依赖包覆盖掉。

  • 使用maven-dependency-plugin,将项目所有的依赖放在同一个目录,实现模块的目录路径统一。通过指定outputDirectory,将项目用到的所有依赖都复制到该目录下面。
<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.1.1</version>
    <executions>
        <execution>
            <id>copy</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>
                    ${project.build.directory}/modules
                </outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
  • 在modulePath中使用<path>${project.build.directory}/modules</path>,将该目录下的所有依赖包都作为模块导入项目。因为项目自身的模块不在该目录下,所以要单独导入,即第一个<path>节点。
<configuration>
    <modulePath> 
        <path>
${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging}
        </path>
        <path>
${project.build.directory}/modules
        </path>  <!-- 添加的代码 -->
    </modulePath>
</configuration>

 添加自身是模块的依赖

接下来改进程序和代码。你们可能知道,在代码中直接使用System.out.println()是不明智的,因为它们无法被配置,因此它们只能达到调试的目的,并且即使发布产品时,它们依然会输出到控制台。让我们使用一个适当的日志框架来代替这个日志声明。

我将使用已经被模块化的slf4j日志框架[https://www.slf4j.org/]。这个选择需要添加两个依赖:API(slf4j-api)和单一实现(slf4j-simple)模块。

 在POM文件中添加如下依赖:

 

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.8.0-beta2</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.8.0-beta2</version>
</dependency>

更新项目的module-info.java:

module ch.frankel.jlink {
    requires org.slf4j.simple;
    requires org.slf4j;
    exports ch.frankel.blog.jlink;
}

这里使用的依赖都是被模块化的,即依赖包的根目录下是自带module-info.java文件的。如果我们引入的是一个未被模块化的依赖包该怎么办呢?

添加非模块化的依赖

这里我们已javax.jms-1.1消息服务依赖为例,这个1.1版本肯定是不具备模块化的,但是在jlink中是不允许使用非模块化的依赖的,所以JDK中提供了一个jdeps工具对非模块化的依赖处理成模块化的。但是我们可以继续通过moditect-maven-plugin插件简单并统一的添加非模块化依赖,代码如下:

  • 添加jms-1.1依赖:
<dependency>
    <groupId>javax.jms</groupId>
    <artifactId>jms</artifactId>
    <version>1.1</version>
</dependency>
  • 在moditect-maven-plugin插件节点中添加add-module-info执行节点,对指定的非模块化依赖包创建并添加module-info.class文件,生成新的依赖包,从而实现对该依赖包的模块化。注意:需要将生成的依赖包路径指向指定的路径,并设置可对包文件进行覆盖写入。如果需要添加多个非模块化依赖,在<modules>节点中按格式添加多个<module>节点即可。
<execution>
    <id>add-module-info</id>
    <phase>package</phase>
    <goals>
        <goal>add-module-info</goal>
    </goals>
    <configuration>
        <modules>
            <module>
                <artifact>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                    <version>1.1</version>
                </artifact>
                <moduleInfo>
                    <name>jms</name>
                </moduleInfo>
            </module>
        </modules>
        <outputDirectory>
            ${project.build.directory}/modules
        </outputDirectory>
        <overwriteExistingFiles>true</overwriteExistingFiles>
    </configuration>
</execution>

至此,你已经完全掌握了对jlink这个工具的使用姿势。一个项目经过jlink工具的模块化,就能实现在未安装JDK9或更高版本的计算机上运行你的Java应用了,因为我们生成的是一个可单独运行的镜像。当然你还可以通过编写一个vbs文件再使用AutoIt3这个工具,生成一个exe执行文件,具体使用视项目情况而定。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章