前言:

通常在采用javafx或tornadofx等框架编写的桌面软件后,若要分发给客户机进行使用,就需要先在目标客户机安装合适版本的JDK,对于客户机来说并不需要关注这一步骤,这也增加了多台客户机分发及使用的成本,客户端更关注的是软件功能的使用。

安装JDK环境对于技术人员而言可能较简单,而对于非技术人员或不是很熟练的实施人员,那这一步就成为了对使用该软件的一个很大的阻碍。
本文描述了如何通过gradle插件将java程序打包为exe,打包成为exe后,就可以将打包产物直接上传至客户机,直接运行软件,省去了安装JDK环境的步骤。

另注:
文末附有demo项目已上传至github,可以作为实际打包的参考。
本文所述方法是基于java JDK1.8,其他版本jdk的打包可能不会适用。

常见的将java项目打包为exe的工具有好几种,例如:exe4j,install4j,launch4j,JavaPackager,还有java14之后的Jpackage等。
这些工具经过我查阅文档,对其各有大致的了解,我的目标是随着项目的迭代,一次轻量级的配置后就不用再过多关注打包环节,打包能做到方便、快捷、一键式。所以带界面的软件如exe4j,install4j这样的工具就不再考虑。
经过尝试后发现采用mavan/gradle
插件:JavaPackager,是最简单方便的,可定制性也足够,该插件能够支持桌面系统windows,linux,mac,能随着项目迭代而简单的通过打包命令来得到最新的exe程序,可谓是相当方便了。

一、前置条件

  • 首先确保你的javafx/java项目已经可以打包为jar包,通过java -jar xxx.jar命令就可以运行并使用。
    如果不能正常打包请自行排查问题,同时也可以参考我提供的demo里的jar包打包方式。
  • 项目打包工具使用gradle(maven项目的步骤也基本一样,只不过是通过xml来配置插件)

二、引入插件

打开项目的build.gradle.kts(kts格式gradle脚本教程参考这里),在其中引用插件JavaPackager (版本可以直接用1.7.0,已经经过我的实际使用验证):

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("io.github.fvarrui:javapackager:1.7.0")
    }
}

apply {
    plugin("io.github.fvarrui.javapackager.plugin")
}

以上插件配置后,点一下gradle快捷栏的刷新按钮:Reload All Gradle Project,此时会从mavenCentral下载该插件,以进行下一步的Plugin Task的配置。

三、注册Plugin Task

build.gradle.kts中注册以下名为packageApp的task,作为实际打包的task,
插件配置项的详细描述可参考:JavaPackager#plugin-configuration-properties

tasks.register<io.github.fvarrui.javapackager.gradle.PackageTask>("packageApp") {
	//依赖build task
    dependsOn(tasks.build)

    // mandatory
    //定义main方法所在class
    mainClass = "com.kamjin.packdemo.MyAppKt"
    
    // optional
    //是否生成msi安装软件,直接false就好,不需要安装
    isGenerateInstaller = false
    //是否必须管理员权限运行程序,此处false
    isAdministratorRequired = false
    //打包的目标平台,此处auto,会使用当前系统环境,因为是在windows上开发所以会自动打包的是windows,也可以指定为windows,此外也可指定为其他的平台,如果想同时生成多个平台。可以多注册几个不同名字的当前task即可。例如packageAppByLinux,packageAppByMac
    platform = io.github.fvarrui.javapackager.model.Platform.auto

	//是否包含jre,这个需要选true,打包后将会包含可运行的jre在exe的同目录下
    isBundleJre = true
    //定义当前开发环境的jre目录
    jrePath = file("D:\Program Files\Java\jdk1.8.0_301\jre")
    //打包的软件名称,可以任意自定义比如demo,打成exe后就是:demo.exe
    appName = "demo"
    //需要打到项目里的其他文件,一般来说不需要,因为打为jar包时就已经将那些需要用的资源都打包进去了,如字体图片等,特殊需求时,该选项可以自行定制需要打包进去的文件
//    additionalResources = kotlin.collections.mutableListOf(file("D:\image\abc.jpg"))
}



四、使用插件(打包)

插件定义完成后,可以直接运行注册的task

java开发exe程序界面 java开发exe客户端_gradle

之后就可以在项目的build/${appName}中找到已经打包好的exe及其他附属文件,如下:

java开发exe程序界面 java开发exe客户端_windows_02


demo目录下内容解释:

  • jre 目录为插件配置中指定的本地jre目录的copy
  • libs 目录里包含当前程序运行所有依赖的第三方jar包
  • demo.exe 为实际的windows可运行程序
  • demo.ico 为图标资源,如果没有自定义则默认是一个咖啡图标
  • extra.properties 该配置文件是手动放入的,也可以通过gradle的Copy Task来完成,此处我是为了演示使用外部配置的方式(将extra.properties放在exe程序同级目录下)

这样生成的demo目录下的所有内容,可通过压缩包的方式分发给各客户机,而相关人员直接解压到某个目录下,就可以直接运行使用。

PS: 如果需要更多的资源定制操作,可以自行定制task动作,拷贝资源,文件替换等,可以参考gradle working_with_files,如果需要定制exe资源等操作,参考JavaPackager plugin-assets

代码地址:

demo代码已上传至github:javafx-gradle-package2exe-demo 该demo项目中包含读取外部及内部配置文件,日志的文件写出,以及exe图标替换范例,采用kotlin+gradle,供实际打包的参考。

结语:

软件开发从来都不是难题,对于给目标客户机的安装和部署,往往才需要更多的精力解决。

另外强烈推荐一下gradle,真的非常好用,定制性足够高,打包脚本可读性很高,主要的重点是gradle的打包速度很快,多模块项目里和maven的对比非常明显,在日复一日的软件开发部署打包环节,能节省大量的时间。再搭配docker-compose或其他编排软件,能大量的提升研发效率。有问题请评论区留言。
随缘更新。再会~