嗨,大家好!我是东哥。
咱们的Java打包工具,终于能让写的Java程序也能像双击桌面上的应用一样,直接运行了,不用用户去安装什么JRE之类的依赖,像普通应用程序一样——直接双击!
作为一个Java开发者,咱们用Java写桌面应用程序,心里其实一直有个小心愿:能不能让这些Java程序双击就运行呢?
日常开发里,我比较喜欢搞些小工具,比如用Swing来做一些实用工具,帮助自己和同事提升工作效率。
可一直有个槽点,那就是Java程序运行起来太“挑剔”了,没JRE不行不说,还得让用户自己去安装,这个使用门槛很高啊。
而且,对于用户来说,直接运行程序的体验才是王道!所以我一直想着能不能把Java程序搞成直接运行的格式,不需要JRE,能双击启动,操作更简单直接。那就来做个工具呗!
既然想搞打包,先看看现有的方案都有什么:
方案一:GraalVM
GraalVM可以把Java程序编译成原生可执行文件,省去了JRE的依赖,而且启动速度也快。
GraalVM的确有它的优势,性能好,而且编译出来的文件跑起来是真流畅。
但它的缺点也不少,比如构建过程复杂,对反射支持有限,写代码还得规避反射类的用法,这对一些大项目来说真心麻烦。
再说了,如果代码调试都变得困难,那我还怎么愉快地修bug呢?
方案二:JLink
JLink这个工具可以生成自定义的JRE,将应用与JRE一起打包成二进制文件。对Java 9+的项目还挺方便,构建出来的文件基本不用担心兼容问题。
然而,JLink的构建也不算简单,生成的文件体积还挺大,对小工具来说有些过重了,压缩之后的体积比不上一个简简单单的EXE。
方案三:Exe4J
Exe4J则更偏向于创建一个EXE启动器,将Jar包与JRE打包在一起,提供了“近乎原生”的体验。
但Exe4J依赖JRE,如果JRE的版本不对,运行效果会打折扣,而且体积上也不够小巧精致。
方案四:批处理和压缩软件的结合
在一些情况下,我们会用批处理文件和压缩软件,生成一个自解压包,启动时调用批处理文件来检查并执行Java程序。
这个方案倒是灵活,调试起来也方便,但它依赖JRE而且不美观,尤其当我们希望应用显得“高大上”时,批处理窗口一闪,体验上就有点low了。
方案五:直接分发Jar包
这种方式最简单,直接把Jar包甩给用户。但这样操作的前提是用户已经安装了JRE,还得让用户手动打开命令行或者右键选择Java运行程序。用起来不够“便捷”,让用户有些无奈,尤其是非开发人员。
综上所述,这些方案各有优缺点,可就是没有一个能够在体验、便捷和性能上都达到“完美”。于是,就有了自己动手“造轮子”的念头!
3. 新方案:自制的打包工具登场!
于是我决定开发一个自用的打包工具,把各种方案的优点结合起来,同时规避它们的缺点。这个工具需要什么功能呢?核心需求就是能让Java程序打包成双击就能运行的EXE文件,不需要用户去配置环境、安装JRE之类的繁琐操作。
技术栈选择
为了实现这个目标,我选择了WinForm来开发前端界面。
WinForm相对简单易用,可以快速做出一个用户友好的图形界面,还能提供选项给用户配置一些细节。通过它的图形化界面,可以方便地完成打包操作,真正做到“一键打包”。
4. 示例代码
说干就干!下面我就用一个简单的Swing项目给大家展示一下项目结构和代码配置。
项目结构
这是一个简单的Swing应用项目,主要文件有pom.xml和核心代码HelloSwing.java。
pom.xml文件
这个文件里包含了Maven的基本配置和一些打包插件的设置。比如,maven-assembly-plugin用于将依赖和代码打包成一个“胖Jar”,这样可以确保打包后的Jar包含所有依赖,运行时不用再额外配置。
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>JavaPackageTool</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
HelloSwing.java
这是应用的主入口。为了让界面看起来更现代,我用了FlatLaf这款美化库。这个小程序会显示一个窗口和一段简单的欢迎消息:
import javax.swing.*;
import com.formdev.flatlaf.FlatLightLaf;
public class HelloSwing {
public static void main(String[] args) {
FlatLightLaf.install();
JFrame frame = new JFrame("Hello Swing");
frame.setSize(400, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("Hello, this is a Java desktop app!", SwingConstants.CENTER);
frame.add(label);
frame.setVisible(true);
}
}
5. 使用步骤
打包流程
具体的打包流程如下:
使用Maven将项目打包成“胖Jar”。有了胖Jar,所有依赖都在同一个文件中,避免了运行时的依赖缺失问题。
使用JLink导出一个精简版的JRE,确保包含Java程序运行所需的基础模块,这样就不需要额外的JRE环境了。
使用自制的工具将胖Jar和精简版JRE打包成EXE文件。
最终的效果就是,一个EXE文件里包含了Java应用和JRE,用户只需要双击EXE文件就能运行Java程序。
效果展示
打包好的EXE文件运行起来就像普通的Windows应用,双击即可打开,再也不用为用户操作卡在“怎么安装Java”而担心了。
经过这番改造,我们的小工具终于变成了真正的“傻瓜式”应用,流畅、直接,用户体验up!
# 最后
这个Java打包工具让分发Java桌面应用变得更加便捷,算是用兴趣来解决了一个实际问题吧。Java写的工具也能变成双击运行的“原生”体验啦!
领取专属 10元无门槛券
私享最新 技术干货