<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Spring Boot - tag - 沐木</title><link>https://oldletter.cn/tags/spring-boot/</link><description>Spring Boot - tag - 沐木</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Thu, 28 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://oldletter.cn/tags/spring-boot/" rel="self" type="application/rss+xml"/><item><title>数据开放平台架构设计（一）：从 SQL2API 到数据开放平台的演进</title><link>https://oldletter.cn/posts/dp-01-architecture/</link><pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/dp-01-architecture/</guid><description><![CDATA[<p>数据开放平台本质上是把&quot;数据变成服务&quot;这件事系统化。我一开始做的是 SQL2API：页面上写 SQL、配置参数，系统自动生成接口。这个工具确实能省掉很多重复 CRUD，但一旦拿去给多个业务方长期使用，问题就不只是&quot;能不能查出数据&quot;了。</p>
<p>真实落地时，大家会马上追问：谁能调这个接口？能看到哪些字段？一次上限查多少？慢查询谁负责？数据源密码放哪？字段改名会影响哪些接口？有没有审计记录？这些都不是 SQL2API 本身能顺手解决的问题。</p>
<p>这一篇聊背景：为什么要从一个 SQL2API 工具，继续往数据开放平台演进，以及平台的架构怎么拆。</p>
<hr>
<h2 id="一从-sql2api-到数据开放平台">一、从 SQL2API 到数据开放平台</h2>
<p>SQL2API 解决的是一个很具体的问题：<strong>把 SQL 变成 API，省掉 CRUD 的模板代码。</strong> 这个能力很有价值，但它只是数据开放链路里的一个环节。</p>
<p>真实场景里，一个完整的数据开放链路长这样：</p>
<ol>
<li><strong>数据接入</strong>：连各种数据源（MySQL、PostgreSQL、ES、Hive、API），把数据接进来</li>
<li><strong>数据加工</strong>：字段映射、格式转换、数据脱敏、聚合计算</li>
<li><strong>服务发布</strong>：把加工后的数据发布成 API，支持多种协议（REST、gRPC、WebSocket）</li>
<li><strong>访问控制</strong>：AK/SK 认证、租户隔离、流量控制、配额管理</li>
<li><strong>监控治理</strong>：调用链追踪、慢查询告警、数据血缘、审计日志</li>
<li><strong>运维管理</strong>：灰度发布、容灾备份、SDK 生成、文档管理</li>
</ol>
<p>SQL2API 只覆盖了第 3 步的一部分。要从&quot;工具&quot;升级为&quot;平台&quot;，需要把这六步都串起来，而且要能长期运维。</p>
<p>类比一下：SQL2API 是一个厨师，能把食材做成菜。数据开放平台是一个餐厅，从采购（数据接入）、备菜（数据加工）、烹饪（服务发布）、上菜（访问控制）、品控（监控治理）到运营（运维管理），全流程都有。</p>
<h3 id="11-为什么不直接开放数据库">1.1 为什么不直接开放数据库</h3>
<p>有人会问：既然本质是查数据，为什么不直接给业务方一个只读账号，让他们连库查？</p>
<p>这个方案短期速度高，长期更麻烦：</p>
<ul>
<li><strong>权限太粗</strong>：数据库账号一般按库、表授权，很难细到&quot;这个应用只能看订单表里的 5 个字段&quot;。</li>
<li><strong>审计断层</strong>：只能看到某个账号执行了 SQL，很难还原到具体应用、具体接口、具体业务场景。</li>
<li><strong>流量不可控</strong>：一个全表扫描或者大分页，就可能把线上库拖慢。</li>
<li><strong>数据口径失控</strong>：每个调用方自己写 SQL，同一个指标可能有三种算法。</li>
<li><strong>变更风险大</strong>：表结构改了，谁受影响靠猜，没人愿意拍胸脯。</li>
</ul>
<p>所以数据库可以作为底座，但不应该直接暴露给调用方。平台要把权限、限流、审计、口径和 SLA 都挡在前面。</p>
<h3 id="12-为什么也不能只靠网关">1.2 为什么也不能只靠网关</h3>
<p>API Gateway 很重要，但它解决的是入口问题：认证、限流、路由、协议转换。它不知道某个接口背后查了哪些表，也不知道手机号字段该不该脱敏，更不知道这个 SQL 是否会扫全表。</p>
<p>数据开放平台需要补的是数据侧能力：</p>
<ul>
<li><strong>权限</strong>：应用级、API 级、字段级、数据范围级权限。</li>
<li><strong>审计</strong>：谁在什么时间，用什么参数，访问了什么数据。</li>
<li><strong>限流与配额</strong>：保护平台，也保护底层数据库。</li>
<li><strong>元数据</strong>：数据源、表、字段、接口、参数、返回结构都要可管理。</li>
<li><strong>血缘</strong>：一个字段变更，要知道影响哪些 API 和调用方。</li>
<li><strong>数据源管理</strong>：连接池、密钥、健康检查、备用数据源不能散落在代码里。</li>
<li><strong>SLA</strong>：接口超时、成功率、慢查询、告警都要有明确指标。</li>
</ul>
<p>这些能力靠网关很难补齐，必须下沉到数据服务平台本身。</p>]]></description></item><item><title>Lombok 进阶指南：从注解原理到 Spring Boot 最佳实践</title><link>https://oldletter.cn/posts/java-01-lombok/</link><pubDate>Mon, 20 Mar 2023 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/java-01-lombok/</guid><description><![CDATA[<blockquote>
<p>📅 2026-05-15 | 🏷️ Java, Lombok, Spring Boot | 📖 阅读约 15 分钟</p></blockquote>
<h2 id="前言">前言</h2>
<p>Lombok 大家都在用，但你真的用对了吗？</p>
<p>很多团队把 Lombok 当成&quot;少写 getter/setter 的工具&quot;，结果在生产环境踩了一堆坑：<code>@Data</code> 导致的 <code>StackOverflowError</code>、序列化失败、MapStruct 不兼容……</p>
<p>这篇文章并非入门教程，重点是<strong>进阶实战指南</strong>，我会从注解的底层原理讲起，结合 Spring Boot 3.x 工程实践，帮你避开那些&quot;写了半天 debug 两小时&quot;的坑。</p>
<p><strong>适合读者</strong>：有 Lombok 基础使用经验，想深入了解原理和成熟实践的 Java 开发者。</p>
<div class="details admonition note open">
    <div class="details-summary admonition-title">
        <i class="icon far fa-pen-to-square" aria-hidden="true"></i>版本说明<i class="details-icon fas fa-angle-right" aria-hidden="true"></i>
    </div>
    <div class="details-content">
        <div class="admonition-content">本文以 Lombok 1.18.x 的常见行为为基准。Spring Boot 3.x + JDK 17/21 用户请参考第五节的兼容性说明；如果使用更高版本 JDK，记得同步升级 Lombok，否则很容易在编译期踩坑。</div>
    </div>
</div>
<hr>
<h2 id="一基础核心注解的隐藏陷阱">一、基础核心注解的&quot;隐藏陷阱&quot;</h2>
<h3 id="11-data方便但危险">1.1 @Data：方便但危险</h3>
<p><code>@Data</code> 是 Lombok 更常用的注解，它等价于 <code>@Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor</code>。听起来很美好，但问题恰恰出在这个&quot;全家桶&quot;上。</p>]]></description></item><item><title>问卷考试系统设计（一）：架构选型与数据模型</title><link>https://oldletter.cn/posts/qnr-01-architecture/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/qnr-01-architecture/</guid><description><![CDATA[<h2 id="为什么还要自建一套">为什么还要自建一套？</h2>
<p>问卷星、腾讯问卷、考试系统都有自己的适用场景，而且这些平台都做得很成熟。普通调研、满意度收集、报名表、简单测评，用它们效率非常高。腾讯问卷有自定义逻辑 / DSL 相关能力，问卷星也支持常见的题目逻辑、API、量表和计分配置。真要只是发一份问卷、收一批答案、导出 Excel，我肯定不会自己造轮子。</p>
<p>我这里说的“问卷考试系统”，更类似是<strong>心理量表 + 考试流程 + 报告引擎 + 内部系统集成</strong>揉在一起的东西。它不是一个单纯的问卷，也不是一个单纯的考试。踩坑之后我发现，问题不在于现成平台有没有某个功能，而在于这些功能是不是能按我们的方式组合、审计、复用和长期维护。</p>
<h3 id="现成问卷平台的边界">现成问卷平台的边界</h3>
<p>问卷星、腾讯问卷这类 SaaS 平台适合快速搭建和运营，优势很明显：</p>
<ul>
<li>题型丰富，跳题、显示逻辑、配额、回收渠道都比较完善</li>
<li>常规计分、基础报告、数据导出基本够用</li>
<li>高级版/企业版通常还会提供 API、团队协作、品牌定制、更多逻辑能力</li>
<li>对非研发团队很友好，产品、运营、老师自己就能配置</li>
</ul>
<p>但到心理量表和内部业务系统结合时，边界就开始出现了。</p>
<p><strong>第一，算法可控性不够。</strong> SCL-90 有 9 个因子分，CES-D 有正性情感题需要反向计分，MMPI 又有 L/F/K 等效度量表。平台可能支持“维度计分”或者“反向题”，但我们还会遇到更细的规则：题目版本修订、常模分层、测谎阈值、T 分/Z 分转换、异常答题判定、人工复核标记。只要规则需要被代码审计、被测试用例覆盖、被历史版本追溯，单靠页面配置就会吃力。</p>
<p><strong>第二，报告不是简单的结果页。</strong> 心理测评的报告往往不是“你得了 78 分”这么简单。它要解释每个维度的含义，要有雷达图、柱状图、风险提示、建议话术，还要能输出 PDF、归档、推送到业务系统。模板一多，报告本身就变成了一个小型内容系统。</p>
<p><strong>第三，数据合规和私有化要求绕不开。</strong> 有些答卷数据涉及个人状态、组织内部评估、学校或企业的敏感信息。即使平台本身安全可靠，业务上也可能要求数据留在自己的库里，权限走自己的组织架构，审计走自己的日志链路。</p>
<p><strong>第四，长期成本和集成成本要算总账。</strong> SaaS 平台按版本、账号、回收量、API 能力收费，短期省事，长期不一定便宜。更麻烦的是集成：用户体系、组织架构、权限、报告归档、消息通知、数据看板都要打通，越往后越类似在平台外面再套一层系统。</p>
<p>所以我末尾的判断是：现成平台并非不能用，重点是<strong>如果核心价值在“量表算法和报告自动化”上，自建会更可控</strong>。</p>
<h3 id="考试系统模型哪里不贴合">考试系统模型哪里不贴合</h3>
<p>考试系统当然也能改。它的流程很完整：题库、试卷、答题、交卷、评分、成绩统计，和我们要做的东西确实很类似。</p>
<p>问题在于考试系统默认有一套很强的假设：答案有对错，题目有标准答案，分数代表掌握程度。心理测评不是这个模型。“近段时间一周你感到情绪低落的频率”这种题，选“没有”和选“经常”只是反映状态，不存在谁更正确。反向题也并非为了“迷惑考生”，重点是为了修正量表方向和控制作答质量。</p>
<p>再比如考试系统常见的防作弊逻辑是切屏检测、人脸识别、随机抽题；心理量表更关心直线作答、过快作答、矛盾回答、测谎题异常。看起来都是“质量控制”，实际关注点完全不同。</p>
<h3 id="什么时候值得自建">什么时候值得自建</h3>
<p>我的经验是，不要一上来就自建。先用这个清单判断：</p>
<table>
  <thead>
      <tr>
          <th>场景</th>
          <th>更适合现成平台</th>
          <th>更适合自建</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>问卷规模</td>
          <td>临时调研、活动报名、满意度收集</td>
          <td>长期产品能力，需要持续迭代</td>
      </tr>
      <tr>
          <td>计分规则</td>
          <td>总分、简单维度、固定报告</td>
          <td>多维度、反向计分、常模、效度量表、复杂阈值</td>
      </tr>
      <tr>
          <td>数据要求</td>
          <td>可接受平台托管和导出</td>
          <td>私有化、审计、权限、合规要求强</td>
      </tr>
      <tr>
          <td>系统集成</td>
          <td>Excel 导出即可</td>
          <td>要打通用户、组织、业务流程、消息、档案</td>
      </tr>
      <tr>
          <td>成本模型</td>
          <td>短期使用，人数不大</td>
          <td>长期高频使用，企业版/API 成本明显</td>
      </tr>
      <tr>
          <td>可维护性</td>
          <td>配置改完就结束</td>
          <td>算法要测试、版本要追溯、报告要复用</td>
      </tr>
  </tbody>
</table>
<p>如果只是普通问卷，用成熟平台更省心；如果要做成企业内部长期运行的测评能力，那就需要一套更工程化的系统。</p>]]></description></item><item><title>Java 后端的 LLM 实战路线：微调、RAG、Agent 全链路拆解</title><link>https://oldletter.cn/posts/ai-02-llm-practice-roadmap/</link><pubDate>Thu, 28 May 2026 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/ai-02-llm-practice-roadmap/</guid><description><![CDATA[<blockquote>
<p>📅 2026-05-28 | 🏷️ LLM, LoRA, RAG, Agent | 📖 阅读约 25 分钟</p></blockquote>
<hr>
<h2 id="写作背景">写作背景</h2>
<p>这篇文章站在 Java 后端的视角写。我的切入点并非训练框架本身，重点是把模型能力接进已有系统：接口怎么设计，流式响应怎么落地，知识库怎么更新，工具调用怎么审计。Python 示例能解释原理，真正上线时还要回到鉴权、限流、日志、回滚和成本控制。
后端同学学习 LLM 时，可以先抓住工程边界：模型负责生成，应用负责上下文、权限、状态和证据。只要这个边界稳住，后续换模型、换向量库、换 Agent 框架都不会牵动整套业务。
Java 生态资料少，不代表 Java 不适合做 AI 应用。训练和实验可以交给 Python，在线服务、管理后台、任务调度、数据治理仍然是 Java 很熟悉的战场。
这篇文章按落地顺序展开：先会调用模型，再做 RAG，再理解微调和 Agent，末尾补评估、部署和安全。
数学细节可以以后补，工程上先把数据链路、接口契约和验证方法跑通。</p>
<hr>
<h2 id="一全景图llm-落地的四层架构">一、全景图：LLM 落地的四层架构</h2>
<div class="mermaid" id="id-11" data-mermaid-definition="Zmxvd2NoYXJ0IFRCCiAgICBBcHBbIuW6lOeUqOWxgu&#43;8muWvueivneOAgeWuouacjeOAgeefpeivhuW6k&#43;OAgeaWh&#43;aho&#43;WKqeaJiyJdCiAgICBPcmNoZXN0cmF0aW9uWyLnvJbmjpLlsYLvvJrlt6XkvZzmtYHjgIHlt6Xlhbfot6/nlLHjgIHkvJror53nirbmgIEiXQogICAgQ2FwYWJpbGl0eVsi6IO95Yqb5bGC77ya5qOA57Si44CB6YeN5o6S44CBRW1iZWRkaW5n44CB6K&#43;E5rWLIl0KICAgIE1vZGVsWyLmqKHlnovlsYLvvJpMTE0gQVBJIOaIluiHqumDqOe9suaOqOeQhuacjeWKoSJdCiAgICBJbmZyYVsi5Z&#43;656GA6K6&#43;5pa977ya5ZCR6YeP57Si5byV44CB5Lia5Yqh5bqT44CB5a&#43;56LGh5a2Y5YKo44CBR1BVIl0KICAgIEFwcCAtLT4gT3JjaGVzdHJhdGlvbgogICAgT3JjaGVzdHJhdGlvbiAtLT4gQ2FwYWJpbGl0eQogICAgT3JjaGVzdHJhdGlvbiAtLT4gTW9kZWwKICAgIENhcGFiaWxpdHkgLS0&#43;IE1vZGVsCiAgICBDYXBhYmlsaXR5IC0tPiBJbmZyYQogICAgTW9kZWwgLS0&#43;IEluZnJh">flowchart TB
    App[&#34;应用层：对话、客服、知识库、文档助手&#34;]
    Orchestration[&#34;编排层：工作流、工具路由、会话状态&#34;]
    Capability[&#34;能力层：检索、重排、Embedding、评测&#34;]
    Model[&#34;模型层：LLM API 或自部署推理服务&#34;]
    Infra[&#34;基础设施：向量索引、业务库、对象存储、GPU&#34;]
    App --&gt; Orchestration
    Orchestration --&gt; Capability
    Orchestration --&gt; Model
    Capability --&gt; Model
    Capability --&gt; Infra
    Model --&gt; Infra</div><p>Java 后端开发者的优势在<strong>应用层和编排层</strong>，你已经会 Spring Boot、会设计 API、会做系统集成。
需要补的是<strong>能力层</strong>（怎么用 RAG/微调提升效果）和<strong>基座层</strong>（怎么选模型、怎么部署）。</p>]]></description></item><item><title>API 鉴权实战（一）：AK/SK、API Key、RBAC 与统一认证授权架构设计</title><link>https://oldletter.cn/posts/api-auth-01-aksk-rbac/</link><pubDate>Tue, 10 Sep 2024 00:00:00 +0000</pubDate><author>mumu</author><guid>https://oldletter.cn/posts/api-auth-01-aksk-rbac/</guid><description><![CDATA[<blockquote>
<p>作者：林 | 系列：API 鉴权实战 | 适合读者：Java 后端/架构师</p></blockquote>
<blockquote>
<p>本文代码使用 Lombok 简化 POJO，所有 getter/setter/builder 均由 Lombok 自动生成。</p></blockquote>
<div class="code-block code-line-numbers open" style="counter-reset: code-block 0">
    <div class="code-header language-xml">
        <span class="code-title"><i class="arrow fas fa-angle-right" aria-hidden="true"></i></span>
        <span class="ellipses"><i class="fas fa-ellipsis-h" aria-hidden="true"></i></span>
        <span class="copy" title=""><i class="far fa-copy" aria-hidden="true"></i></span>
    </div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="c">&lt;!-- pom.xml --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;dependency&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;groupId&gt;</span>org.projectlombok<span class="nt">&lt;/groupId&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;artifactId&gt;</span>lombok<span class="nt">&lt;/artifactId&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;scope&gt;</span>provided<span class="nt">&lt;/scope&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/dependency&gt;</span></span></span></code></pre></div></div>
<hr>
<h2 id="一背景为什么要做-api-鉴权">一、背景：为什么要做 API 鉴权</h2>
<p>对外暴露 API 时，两个核心问题绕不开：</p>
<ol>
<li><strong>调用方是谁？</strong>（认证，Authentication）</li>
<li><strong>他能做什么？</strong>（授权，Authorization）</li>
</ol>
<p>简单的内部系统可能用一个 API Key 就够了。但当系统开始支持多租户、第三方接入、AI 开放平台、文件上传、额度控制时，单一的鉴权方式撑不住。你需要一套完整的体系：从密钥管理到权限判断，从缓存设计到上下文传递。</p>
<p>本文从更基础的 API Key 讲起，逐步构建到 PDP 策略决策点，把认证授权的全链路打通。</p>
<hr>
<h2 id="二五种鉴权方式详解">二、五种鉴权方式详解</h2>
<h3 id="21-api-key">2.1 API Key</h3>
<p><strong>原理：</strong> 给每个调用方分配一个唯一的密钥字符串，请求时放在 Header 里，服务端查库校验。</p>
<p><strong>适用场景：</strong> 内部服务间调用、快速原型、低安全要求的公开 API。</p>
<p><strong>不适用场景：</strong> 对外开放的 API，API Key 是静态的，明文传输，一旦被截获攻击者就能冒充调用方。</p>]]></description></item></channel></rss>