前言:
通常在采用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
之后就可以在项目的build/${appName}
中找到已经打包好的exe及其他附属文件,如下:
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或其他编排软件,能大量的提升研发效率。有问题请评论区留言。
随缘更新。再会~