利用Golang打包jar应用

打印 上一主题 下一主题

主题 1731|帖子 1731|积分 5193

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
背景

想把本身的一个SpringBoot应用打包成可实验文件。看看Golang是如何做到的。
Go 的 go:embed 功能介绍与打包 JAR 文件示例

go:embed 是 Go 1.16 引入的一个强大功能,它允许在编译时将外部文件或目录嵌入到 Go 程序中。下面介绍如何利用 go:embed 来嵌入 JAR 文件。
1. go:embed 底子介绍

基本特性



  • 编译时嵌入文件内容
  • 支持嵌入单个文件、多个文件或整个目录
  • 支持三种嵌入类型:

    • string - 用于文本文件
    • []byte - 用于二进制文件
    • embed.FS - 用于文件系统(支持多个文件/目录)

基本语法

  1. import "embed"
  2. //go:embed filename.txt
  3. var fileContent string
  4. //go:embed image.png
  5. var imageData []byte
  6. //go:embed templates/*
  7. var templatesFS embed.FS
复制代码
2. 嵌入 JAR 文件示例

假设你有一个需要嵌入的 app.jar 文件,以下是完整示例:
项目结构

  1. project/
  2. ├── embedded/
  3. │   └── app.jar    # 要嵌入的JAR文件
  4. ├── main.go
  5. └── go.mod
复制代码
代码实现

  1. package main
  2. import (
  3.         "embed"
  4.         "io"
  5.         "log"
  6.         "os"
  7.         "path/filepath"
  8. )
  9. //go:embed embedded/app.jar
  10. var jarFile []byte
  11. func main() {
  12.         // 指定输出路径(可以是临时目录或特定位置)
  13.         outputPath := filepath.Join(os.TempDir(), "app.jar")
  14.        
  15.         // 将嵌入的JAR写入文件系统
  16.         err := os.WriteFile(outputPath, jarFile, 0755)
  17.         if err != nil {
  18.                 log.Fatalf("Failed to write JAR file: %v", err)
  19.         }
  20.        
  21.         log.Printf("JAR file extracted to: %s", outputPath)
  22.        
  23.         // 现在你可以使用这个JAR文件,比如通过exec.Command运行它
  24.         // exec.Command("java", "-jar", outputPath)
  25. }
复制代码
3. 高级用法:嵌入多个文件或目录

假如你有多个 JAR 文件需要嵌入:
  1. //go:embed embedded/*.jar
  2. var jarFiles embed.FS
  3. func main() {
  4.         // 列出所有嵌入的JAR文件
  5.         entries, err := jarFiles.ReadDir("embedded")
  6.         if err != nil {
  7.                 log.Fatal(err)
  8.         }
  9.        
  10.         // 提取所有JAR文件
  11.         for _, entry := range entries {
  12.                 if filepath.Ext(entry.Name()) == ".jar" {
  13.                         data, err := jarFiles.ReadFile("embedded/" + entry.Name())
  14.                         if err != nil {
  15.                                 log.Printf("Failed to read %s: %v", entry.Name(), err)
  16.                                 continue
  17.                         }
  18.                        
  19.                         outputPath := filepath.Join(os.TempDir(), entry.Name())
  20.                         err = os.WriteFile(outputPath, data, 0755)
  21.                         if err != nil {
  22.                                 log.Printf("Failed to write %s: %v", entry.Name(), err)
  23.                                 continue
  24.                         }
  25.                        
  26.                         log.Printf("Extracted %s to %s", entry.Name(), outputPath)
  27.                 }
  28.         }
  29. }
复制代码
4. 利用注意事项


  • 路径规则

    • go:embed 路径是相对于包罗该指令的Go源文件的
    • 不能包罗 . 或 .. 等路径组件
    • 不能匹配到父目录中的文件

  • 文件巨细限制

    • Go 1.16+ 对嵌入文件巨细没有硬性限制
    • 但非常大的文件可能会增加编译时间和二进制巨细

  • 构建约束

    • 嵌入的文件必须在构建时可用
    • 假如文件不存在,构建会失败

  • 安全考虑

    • 提取嵌入文件时要注意目标路径的权限
    • 考虑利用暂时目录并在程序退出时清算

5. 现实应用场景


  • 打包Java应用:将依靠的JAR文件嵌入Go程序,然后通过exec.Command调用Java运行
  • 嵌入式数据库:如SQLite数据库文件
  • Web服务器资源:HTML/CSS/JS等前端资源
  • 配置文件:默认配置模板
6. 完整示例:运行嵌入的JAR

  1. package main
  2. import (
  3.         "embed"
  4.         "log"
  5.         "os"
  6.         "os/exec"
  7.         "path/filepath"
  8. )
  9. //go:embed app.jar
  10. var jarFile []byte
  11. func main() {
  12.         // 创建临时文件
  13.         tmpFile, err := os.CreateTemp("", "embedded-*.jar")
  14.         if err != nil {
  15.                 log.Fatal(err)
  16.         }
  17.         defer os.Remove(tmpFile.Name()) // 程序退出时删除
  18.        
  19.         // 写入JAR内容
  20.         if _, err := tmpFile.Write(jarFile); err != nil {
  21.                 log.Fatal(err)
  22.         }
  23.         if err := tmpFile.Close(); err != nil {
  24.                 log.Fatal(err)
  25.         }
  26.        
  27.         // 执行Java命令
  28.         cmd := exec.Command("java", "-jar", tmpFile.Name())
  29.         cmd.Stdout = os.Stdout
  30.         cmd.Stderr = os.Stderr
  31.        
  32.         log.Println("Starting Java application...")
  33.         if err := cmd.Run(); err != nil {
  34.                 log.Fatalf("Java application failed: %v", err)
  35.         }
  36. }
复制代码
通过这种方式,你可以将Java应用程序打包到Go二进制文件中,然后通过Go程序来分发和启动它。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

千千梦丶琪

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表