Track My Cash: 使用 Spring Boot、Vanilla JS 和 Gemini 构建安全、解耦的账本
I’m happy to help translate the article, but I need the actual text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll then provide the Simplified‑Chinese version while preserving the original formatting, markdown, and any code blocks or URLs.
Source: …
我用 Google Gemini 构建的项目
我创建了 BookKeeping,这是一款全栈金融账本应用,专门解决一个非常具体的问题:在不使用臃肿会计工具的情况下,记录我借给朋友的金钱。
- 前端 – 原生 JavaScript、HTML 和 CSS(零框架依赖),安全部署在 Google Cloud Run 上。
- 后端 – Java、Spring Boot 3、Spring Security 6,以及托管在 Render 上的 PostgreSQL 数据库。
在整个开发周期中,Google Gemini 充当了我的配对编程伙伴,帮助我拼接解耦架构中的棘手部分。
Gemini 的帮助方式
- 构建安全流程 – 使用 HttpOnly Cookie 和标准 Bearer Token 实现了无状态 JWT 认证。
- 处理浏览器安全障碍 – 通过设计严格的 CORS 与 JSON‑payload 策略,天然抵御了 CSRF 攻击,成功绕过了诸如 Safari ITP 等激进的第三方 Cookie 阻止机制。
- 构建数学引擎 – 共同实现了自定义的 “Partial Repayment” 算法,能够动态减少贷款金额,并在余额归零时自动删除数据库记录。
- 搭建 Cloud Run Docker 环境 – 为前端构建了轻量的 Alpine‑Nginx 容器。Gemini 指出 Cloud Run 会覆盖标准端口绑定,于是我们在部署时加入了动态的
nginx.conf.template,在其中注入 Cloud Run 的$PORT环境变量。 - 设计原生操作系统本地化 – 修复了多币种逻辑中硬编码的
'en-US'区域设置。通过向Intl.NumberFormat传入undefined,UI 现在会继承操作系统的本地化设置(例如正确的欧元格式)。
关于认证的说明
登录系统故意保持简洁。由于该应用针对的是高度聚焦的个人任务(记录我们自己的金钱),并不需要复杂的 OAuth 或多角色层级。简单的无状态 JWT 登录让应用保持轻量,并且完全由我们自行掌控。
演示
- GitHub Pages: https://rohithv07.github.io/BookKeeping/
- Cloud Run URL: (在此插入您的 Cloud Run URL)
## 记账
记录我们借给他人的债务。
## 实现内容
### Spring Boot 应用
- 使用 **Java 21** 和 **Gradle** 构建的强大 REST API。
### 数据库模型
| 模型 | 字段 |
|------|------|
| **Borrower** | `name`, `email`, `phone` |
| **Loan** | `amount`, `dateLent`, `dueDate`(借出后恰好 1 个月),`status`(`ACTIVE` \| `REPAID`) |
### 核心 API 端点
| 方法 | 端点 | 描述 |
|------|------|------|
| `POST` | `/api/borrowers` | 创建新的借款人 |
| `GET` | `/api/borrowers` | 列出所有借款人 |
| `POST` | `/api/loans` | 创建新的贷款 |
| `GET` | `/api/loans` | 列出所有贷款 |
| `PUT` | `/api/loans/{id}/repay` | 将贷款标记为已偿还 |
### 通知任务
- **`NotificationService`** 每天 **08:00 AM** 运行。
- 它查询 `dueDate` 为 **今天或更早** 且状态为 `ACTIVE` 的贷款,并向指定的个人 Gmail 账户发送邮件。
### 系统架构升级
- **基于接口的设计** – 服务层使用契约(`BorrowerService`、`LoanService`)实现松耦合,便于扩展。
- **数据传输对象 (DTO)** – 所有 API 负载均由 `BorrowerDto` 和 `LoanDto` 表示。
## 我学到的
- **安全与分布式环境** – 将前端(Google Cloud Run)与后端(Render)分离,突显了跨域 Cookie 处理、预检 `OPTIONS` 请求以及浏览器隐私保护。
- **多租户与数据迁移** – 添加用户配置文件映射导致旧数据看似“丢失”。通过与 Gemini 合作,我们构建了一个 `DataMigrationRunner`,在启动时扫描 PostgreSQL 中的孤立记录,并通过新外键重新关联它们。
- **交互式调试** – 与其在 StackOverflow 上翻找,不如将日志粘贴到 Gemini,让我们快速理解 Nginx Alpine 模板处理,并通过一次变量替换修复了 `gcloud run deploy` 的端口绑定错误。
## Google Gemini 反馈
### 做得好的方面
- **Context Retention** – Gemini 能够跟踪复杂的文件结构,使得对 `JwtAuthenticationFilter` 的精确重构成为可能,以同时支持 cookie 和 Bearer token。
- **Deep Architectural Awareness** – 这在 PostgreSQL 模式迁移和 Cloud Run Nginx 优化期间显得尤为关键。
### 遇到的摩擦点
- **Premature Fix Suggestions** – Gemini 有时会在我描述完前端 JavaScript 问题之前就尝试后端修复(例如,由于简单的字符串插值错误导致的 `onclick` 误触)。
- **Superficial Script Loops** – 该代理有时会执行一些琐碎的内部脚本(例如 `echo "do something"`)以满足系统任务边界检查,然后才给出实际答案。