# 构建与部署 本章介绍「汇账」的构建方式、分发形态与生产部署流程。 ## 前置条件 - **JDK 21**(Temurin 21 LTS,含 `jpackage`) - **Node.js**(构建前端时需要) - 依赖仓库:本地 Nexus(Maven)与 verdaccio(npm);构建时经 `-I nexus-init.gradle` 注入 Maven 私服地址 ## 开发模式 前后端分离,便于调试: ```bash # 后端(默认 8080) cd ledgerly ./gradlew bootRun # Windows: gradlew.bat bootRun # 前端(默认 5173,接口代理到 8080) cd ledgerly/frontend npm run dev ``` - 后端地址:`http://localhost:8080`,接口文档 `http://localhost:8080/doc.html` - 前端地址:`http://localhost:5173`,`/api` 经 Vite 代理到后端 8080 ## 构建可执行 jar(前后端一体化) `bootJar` 会先执行前端 `npm run build`,再把 `frontend/dist` 复制到 jar 内的 `BOOT-INF/classes/static/`,单文件同时提供页面与接口。 ```bash # 普通 jar(无 GUI,不含 JavaFX) ./gradlew -I nexus-init.gradle bootJar # 带 GUI 启动器的 jar ./gradlew -I nexus-init.gradle bootGuiJar # 或使用宿主机脚本(一次产出两者) ./package.sh ``` 产物文件名携带目标 JDK 版本: | 任务 | 产物 | 说明 | |---|---|---| | `bootJar` | `build/libs/ledgerly-0.1-jdk21.jar` | 普通服务 jar | | `bootGuiJar` | `build/libs/ledgerly-0.1-jdk21-gui.jar` | 入口为桌面启动器 | 启动(默认 8080,可另指定端口): ```bash java -jar build/libs/ledgerly-0.1-jdk21.jar --server.port=18081 ``` 构建任务链(`build.gradle`):`npmInstall` → `frontendLint` → `frontendBuild` → `bootJar`;`check` 任务另挂 Spotless、Checkstyle、SpotBugs。代码检查不通过会中断构建与打包,详见[开发环境与规范](/dev/development)。 ::: tip 提示 jar 内置的前端为生产构建,访问时与后端同源,无需额外的反向代理。 ::: 为减小可执行 jar 体积,普通 jar 与 GUI jar 均做了裁剪:AI 调用改用 Spring `RestClient` 直连 OpenAI 兼容接口(不再打包 OpenAI Java SDK);接口文档仅保留 `/v3/api-docs`(JSON),Knife4j 的 `doc.html` UI 依赖为 `developmentOnly`,不进生产 jar;普通 jar 通过 `exclude` 排除桌面启动器包,保持无 JavaFX 依赖。 运行时首次配置或切换数据库时,「测试连接」与「保存并应用」会通过 SSE **实时推送执行进度**(连接测试、建表、结构迁移、数据源切换等)。 ## 构建免安装应用(jpackage app-image) `jpackageAppImage` 聚合任务一次生成两个 app-image,自带精简运行时,双击即用;**仅能为当前操作系统生成**(Windows 上生成 Windows 产物,Linux 上生成 Linux 产物)。 ```bash ./gradlew -I nexus-init.gradle jpackageAppImage # 也可单独执行 jpackageServerAppImage / jpackageGuiAppImage ``` | 任务 | 应用名 | 源 jar | 入口 | |---|---|---|---| | `jpackageServerAppImage` | `LedgerlyServer` | `bootJar` | `bin/LedgerlyServer`(Windows 为 `LedgerlyServer.exe`,附带控制台) | | `jpackageGuiAppImage` | `Ledgerly` | `bootGuiJar` | `bin/Ledgerly`(Windows 为 `Ledgerly.exe`) | 产物位于 `build/jpackage/LedgerlyServer/` 与 `build/jpackage/Ledgerly/`。 图标不随源码分发:打包时 `downloadAppIcon` 从 `src/main/resources/launcher/icon.url` 下载源图,再由 `tools/IconGen.java` 生成平台图标(`ico` / `icns` / `png`);可用 `-PsourceIcon=` 指定本地源图。 ## 桌面 GUI 启动器 `cn.rosercode.ledgerly.launcher` 提供系统托盘 + 控制窗口的桌面启动器(进程内启停服务、设置端口、打开浏览器、实时查看日志、单实例运行),仅打入带 GUI 的 jar,普通 jar 不含 JavaFX 依赖。 ## 分发形态 | 形态 | 构建方式 | 说明 | |---|---|---| | 普通 jar | `bootJar` | 需 JDK 21 运行,跨平台 | | 带 GUI 启动器 jar | `bootGuiJar` | 内含桌面启动器,跨平台(打包含 JavaFX 全平台原生库) | | Windows 免安装包 | `jpackageAppImage` | 在 Windows 上构建,zip 分发 | | Linux 免安装包 | `jpackageAppImage` | 在 Linux 上构建,tar.gz 分发 | ## 发布产物与下载地址 发布产物上传至阿里云 OSS(桶 `adccrac`,对象键前缀 `ledgerly/release/<版本>/`),通过 10 年有效的长期签名 URL 对外提供下载;每个文件同时提供 `.sha256` 校验文件与汇总清单 `SHA256SUMS`。 当前工程版本为 `0.1`;最新下载地址见使用文档的[下载与安装](/guide/download)(该页链接指向已上传的发布产物)。 上传方式: - Linux 产物(jar 与 Linux app-image 包):工作区根 `oss-release-upload.py`,需在带 `oss2` 的虚拟环境执行(如 `20260807_131528/oss-venv`),上传后输出长期签名 URL。 - Windows 产物(Windows app-image 包):在 Windows 主机上用 Node 脚本(`ali-oss` + STS)直接上传,不回传本地。 ## 生产部署(云服务器) 服务部署在云服务器 `101.35.20.223` 的 `/opt/ledgerly` 目录,由 Docker Compose 编排: | 容器 | 镜像 | 端口 | 说明 | |---|---|---|---| | `ledgerly` | `eclipse-temurin:21-jre` | `127.0.0.1:15180 → 8080` | 挂载 `app/ledgerly-0.1.jar`、`config/`、`data/`,JVM `-Xmx512m` | | `ledgerly-docs` | `nginx:1.27` | `127.0.0.1:15181 → 80` | 挂载 `docs-dist/` 与 `docs/nginx.conf` | 云上 `nginx` 容器反代这两个回环端口并终止 HTTPS,证书由 `certbot` 容器负责续期: - 服务:[https://finance.rosercode.cn](https://finance.rosercode.cn) - 文档:[https://docs.finance.rosercode.cn](https://docs.finance.rosercode.cn) ### 安全配置 - **JWT 签名密钥**:默认使用内置密钥签发 Token(有效期 24 小时);生产环境可通过环境变量 `JWT_SECRET` 覆盖,未配置时回退内置默认值,避免个人自托管场景重启后登录态失效。 - **CORS 放行来源**:仅放行本机与局域网来源——`localhost`、`127.0.0.1`、`[::1]`、`192.168.*`、`10.*`、`172.*`(任意端口),并允许携带凭证;生产环境前后端同源,无需额外的跨域配置。 ### 发布流程 服务(构建 → 复制 → 重启): ```bash # 1) 本地构建 jar(见上) # 2) 复制到云端部署目录,目标文件名须与 compose 挂载一致 scp -i ~/.ssh/id_ed25519_www.rosercode.cn \ build/libs/ledgerly-0.1-jdk21.jar \ root@101.35.20.223:/opt/ledgerly/app/ledgerly-0.1.jar # 3) 重启容器 ssh -i ~/.ssh/id_ed25519_www.rosercode.cn root@101.35.20.223 \ 'cd /opt/ledgerly && docker compose restart' ``` 文档站(构建 → 覆盖 `docs-dist`,目录挂载即时生效): ```bash cd doc-site && npm run docs:build scp -i ~/.ssh/id_ed25519_www.rosercode.cn -r .vitepress/dist/* \ root@101.35.20.223:/opt/ledgerly/docs-dist/ ``` > 云服务器不能直连 DockerHub,新镜像需本地 `docker save | gzip` → `scp` → 云端 `docker load` 导入。 ## 相关文档 - [项目结构](/dev/project-structure) - [开发环境与规范](/dev/development) - [下载与安装(使用文档)](/guide/download) - [快速开始(使用文档)](/guide/getting-started)