Technical Documentation: chillzhuang/SpringBlade
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
SpringBlade微服务开发平台
- 采用前后端分离的模式,前端架构 Saber (基于 Vue3、Element-Plus)
- 后端采用SpringCloud全家桶,并同时对其基础组件做了高度的封装,单独开源出一个框架:BladeTool
- BladeTool已推送至Maven中央库,直接引入即可,减少了工程的臃肿,也可更注重于业务开发
- 集成Sentinel从流量控制、熔断降级、系统负载等多个维度保护服务的稳定性。
- 注册中心、配置中心选型Nacos,为工程瘦身的同时加强各模块之间的联动。
- 极简封装了多租户底层,用更少的代码换来拓展性更强的SaaS多租户系统。
- 借鉴OAuth2,自研多终端认证系统,可控制子系统的token权限互相隔离。
- 借鉴Security,自研Secure模块,采用JWT做Token认证,可拓展集成Redis等细颗粒度控制方案。
- 稳定生产了九年,经历了从 Camden -> Hoxton -> 2025 的技术架构,也经历了从fat jar -> docker -> k8s + jenkins的部署架构。
- 项目分包明确,规范微服务的开发模式,使包与包之间的分工清晰。
架构图
核心技术栈
| 技术栈 | 版本 |
|---|---|
| Java | 21+ |
| NodeJS | 18+ |
| Spring | 7.0.8 |
| Spring Boot | 4.1.0 |
| Spring Cloud | 2025.1.2 |
| Spring Cloud Alibaba | 2025.1.0.0 |
| Nacos Alibaba | 3.2.2 |
| Mybatis Plus | 3.5.17 |
工程结构
SpringBlade
├── blade-auth -- 授权服务提供
├── blade-common -- 常用工具封装包
├── blade-gateway -- Spring Cloud 网关
├── blade-ops -- 运维中心
├ ├── blade-admin -- spring-cloud后台管理
├ ├── blade-develop -- 代码生成
├ ├── blade-report -- 报表模块
├ ├── blade-resource -- 资源模块
├ ├── blade-seata-order -- seata分布式事务demo
├ ├── blade-seata-storage -- seata分布式事务demo
├── blade-service -- 业务模块
├ ├── blade-demo -- 示例模块
├ ├── blade-desk -- 工作台模块
├ ├── blade-log -- 日志模块
├ └── blade-system -- 系统模块
├── blade-service-api -- 业务模块api封装
├ ├── blade-demo-api -- 示例api
├ ├── blade-desk-api -- 工作台api
├ ├── blade-dict-api -- 字典api
├ ├── blade-scope-api -- 权限api
├ ├── blade-system-api -- 系统api
└── └── blade-user-api -- 用户api官方信息
| 简介 | 内容 |
|---|---|
| 官网地址 | https://bladex.cn |
| 问答社区 | https://sns.bladex.cn |
| 会员计划 | SpringBlade会员计划 |
| 交流一群 | 477853168 (满) |
| 交流二群 | 751253339 (满) |
| 交流三群 | 784729540 (满) |
| 交流四群 | 1034621754 (满) |
| 交流五群 | 946350912 (满) |
| 交流六群 | 511624269 (满) |
| 交流七群 | 298061704 (满) |
| 交流八群 | 1078507904 |
官方产品
| 简介 | 演示地址 |
|---|---|
| BladeX企业级开发平台 | https://saber3.bladex.cn |
| BladeX可视化数据大屏 | https://data.bladex.cn |
| BladeX物联网开发平台 | https://iot.bladex.cn |
| BladeXAI大模型平台 | https://ai.bladex.cn/ |
前端项目
| 简介 | 地址 |
|---|---|
| 前端框架Saber3(基于Vue3) | https://gitee.com/smallc/Saber3 |
| 前端框架Saber(基于Vue2) | https://gitee.com/smallc/Saber2 |
| 前端框架Sword(基于React) | https://gitee.com/smallc/Sword |
后端项目
| 简介 | 地址 |
|---|---|
| 核心框架项目地址 | https://gitee.com/smallc/blade-tool |
| 后端Gitee地址 | https://gitee.com/smallc/SpringBlade |
| 后端Github地址 | https://github.com/chillzhuang/SpringBlade |
| 后端SpringBoot版 | https://gitee.com/smallc/SpringBlade/tree/boot/ |
安全手册
| 简介 | 地址 |
|---|---|
| Blade安全手册 | https://www.yuque.com/bladex/safety |
技术文档
| 简介 | 地址 |
|---|---|
| SpringBlade开发手册一览 | https://gitee.com/smallc/SpringBlade/wikis/SpringBlade开发手册 |
| SpringBlade常见问题集锦 | https://sns.bladex.cn/article-14966.html |
| SpringBlade基于Rainbond部署 | https://www.rainbond.com/docs/micro-service/example/blade |
免费公开课
开源协议
Apache Licence 2.0 (英文原文)
Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件)。
需要满足的条件如下:
- 需要给代码的用户一份Apache Licence
- 如果你修改了代码,需要在被修改的文件中说明。
- 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。
- 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。
Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。
用户权益
- 允许免费用于学习、毕设、公司项目、私活等,但请保留源码作者信息。
- 对未经过授权和不遵循 Apache 2.0 协议二次开源或者商业化我们将追究到底。
- 参考请注明:参考自 SpringBlade:https://gitee.com/smallc/SpringBlade。
Overview (`blade-ops/blade-seata-order/README.md`)
-- 创建 order库、业务表、undo_log表
create database seata_order;
use seata_order;
DROP TABLE IF EXISTS tb_order;
CREATE TABLE tb_order (
id int(11) NOT NULL AUTO_INCREMENT,
user_id varchar(255) DEFAULT NULL,
commodity_code varchar(255) DEFAULT NULL,
count int(11) DEFAULT 0,
money int(11) DEFAULT 0,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE undo_log
(
id BIGINT(20) NOT NULL AUTO_INCREMENT,
branch_id BIGINT(20) NOT NULL,
xid VARCHAR(100) NOT NULL,
context VARCHAR(128) NOT NULL,
rollback_info LONGBLOB NOT NULL,
log_status INT(11) NOT NULL,
log_created DATETIME NOT NULL,
log_modified DATETIME NOT NULL,
ext VARCHAR(100) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY ux_undo_log (xid, branch_id)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;
Overview (`blade-ops/blade-seata-storage/README.md`)
-- 创建 storage库、业务表、undo_log表
create database seata_storage;
use seata_storage;
DROP TABLE IF EXISTS tb_storage;
CREATE TABLE tb_storage (
id int(11) NOT NULL AUTO_INCREMENT,
commodity_code varchar(255) DEFAULT NULL,
count int(11) DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY (commodity_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE undo_log
(
id BIGINT(20) NOT NULL AUTO_INCREMENT,
branch_id BIGINT(20) NOT NULL,
xid VARCHAR(100) NOT NULL,
context VARCHAR(128) NOT NULL,
rollback_info LONGBLOB NOT NULL,
log_status INT(11) NOT NULL,
log_created DATETIME NOT NULL,
log_modified DATETIME NOT NULL,
ext VARCHAR(100) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY ux_undo_log (xid, branch_id)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8;
-- 初始化库存模拟数据
INSERT INTO seata_storage.tb_storage (id, commodity_code, count) VALUES (1, 'product-1', 9999999);
INSERT INTO seata_storage.tb_storage (id, commodity_code, count) VALUES (2, 'product-2', 0);
Overview (`doc/nacos/README.md`)
- SpringBlade的注册中心
- 具体文档详见:https://nacos.io/zh-cn/docs/quick-start.html
- docker部署详见:https://github.com/nacos-group/nacos-docker
- SpringBlade配置详见:https://www.kancloud.cn/smallchill/blade/913215
Overview (`.claude/skills/avue-design/README.md`)
avue-design Skill 集合
Avue 组件代码生成与配置指南,基于 Avue v3.8.2 (Vue3 + Element-Plus) 文档构建。
概述
本 Skill 集合为 Claude Code 提供完整的 Avue 组件库知识,使其能够根据用户需求精准生成 Avue 组件代码。覆盖 CRUD 表格、动态表单、树组件、数据展示等全部 Avue 组件,支持 Composition API 和 Options API 两种代码风格。
目录结构
avue-design/
├── SKILL.md # 主入口 - 概览、路由、速查表
├── README.md # 本文件
└── references/ # 参考文档(按需加载)
│
│── 基础配置 ───────────────────────
├── global-config.md # 安装、全局配置、国际化、云存储
├── api-style-guide.md # Composition API vs Options API 完整模板
├── utility-apis.md # 16个全局工具函数 ($DialogForm, $Export 等)
│
│── avue-crud 表格组件 ─────────────
├── crud-core.md # 组件属性、Option配置、按钮、弹窗、分页、事件、方法、插槽
├── crud-column.md # 列配置、字典、Props映射、排序过滤、格式化渲染
├── crud-search.md # 搜索栏配置、搜索字段属性、级联搜索
├── crud-form-dialog.md # 弹窗表单配置、验证规则、字段控制、分组、权限
├── crud-features.md # 树表、虚拟滚动、卡片模式、行编辑、导入导出、拖拽、插件模式
│
│── avue-form 表单组件 ─────────────
├── form-core.md # 组件属性、布局、按钮、Column通用属性、事件、方法、插槽
├── form-field-types.md # 全部27+字段类型详细配置(input含13子类型、select、date等)
├── form-advanced.md # 字典、验证、动态子表单、文件上传(含云存储)、字段联动、Mock
│
│── 其他组件 ─────────────────────
├── tree-component.md # avue-tree 树组件完整API
├── data-display.md # 23个数据展示组件
└── other-components.md # Card、DialogForm、Flow、Login、Chat等22个独立组件模块说明
1. 基础配置(3个文件)
| 文件 | 内容 |
|---|---|
global-config.md |
npm安装、Element-Plus集成、全局crudOption/formOption、阿里云/七牛/腾讯COS云存储配置、水印配置、国际化、外部库CDN |
api-style-guide.md |
Composition API 和 Options API 两种风格的完整 CRUD 页面模板,包含详细的差异对照表和转换规则 |
utility-apis.md |
全部16个Avue工具函数:$DialogForm、$Clipboard、$ImagePreview、$Print、$Export、$Log、findObject、deepClone等 |
2. avue-crud 表格组件(5个文件)
这是 Avue 最核心的组件,文档最为丰富。
| 文件 | 内容 |
|---|---|
crud-core.md |
组件属性(21个)、Option表格级属性(索引/选择/展开/行/菜单/网格/工具栏共80+属性)、按钮配置(25+)、弹窗配置(19个)、分页(8个)、事件(35+)、方法(40+含行内编辑/滚动/搜索/视图方法组)、插槽(22+) |
crud-column.md |
列通用属性(20+含hide/cell/detail控制)、字典配置(7个属性+Props映射)、字典联动、显示控制、多级表头、排序过滤、formatter/render/html格式化、合计行、合并行列、搜索字段属性(20+含searchDisabled/searchControl/renderSearch)、表单字段属性(20+) |
crud-search.md |
搜索变量绑定(双API风格)、全局搜索属性(15+)、列级搜索属性(14个)、类型覆盖、折叠、级联联动、自定义插槽 |
crud-form-dialog.md |
弹窗属性(15个)、beforeOpen/beforeClose回调、验证规则(async-validator)、字段display/disabled控制、默认值、control联动、分组/标签页、数据过滤、权限控制 |
crud-features.md |
树表(基本/懒加载)、虚拟滚动(3.7.0+)、卡片网格模式(3.4.0+)、行编辑(单击/双击)、Excel导入导出(含对话框选项)、行/列拖拽排序、合计行、父子表、行复制、高级筛选(8种操作符)、列管理器、权限控制(对象/行级函数)、CRUD插件模式(Mixin)、API/Option文件模板、动态配置切换 |
3. avue-form 表单组件(3个文件)
| 文件 | 内容 |
|---|---|
form-core.md |
组件属性(9个含v-model:status)、Option属性(20个含formWidth/tabsActive/tabsType/tabsVerifyAll/filterDic/filterNull)、布局(栅格/分组/标签页/帮助文字)、Group属性(8个含arrow/display/header)、按钮配置(12个)、Column通用属性(25+)、事件(6个含change/tab-click/error/mock-change)、方法(12个含show/hide/scrollToField/getField)、插槽(6个)、两种API风格完整示例 |
form-field-types.md |
全部27+字段类型完整配置:input(含14子类型:password/textarea/search/phone/currency/bankCard/idCard/email/code/plate/ip/mac/uscc + formatters/parser)、number、select(含all/noMatchText)、cascader、checkbox、radio、date(含disabledDate/shortcuts/unlinkPanels)、time(含arrowControl + TimeSelect自动切换)、switch、upload(含dragFile/oss/cropperOption)、tree、input-tag(含min/max/prefix/suffix)、mention(含split/prefix/whole)、input-table(含children/dialogWidth)、color、icon(含dialogWidth/分组iconList)、map(含mapChange/dialogWidth/值格式说明)、rate、slider、array/img/url、dynamic(含max + 完整children配置12属性)、title、input-cron |
form-advanced.md |
字典配置(本地/远程/格式化/联动/更新)、验证规则(基本/类型/自定义/方法)、动态子表单(表格/表单模式)、文件上传(回调/水印/云存储/数据格式)、字段联动(control/Promise)、数据格式(深层绑定/过滤)、自定义插槽、Mock数据 |
4. 其他组件(3个文件)
| 文件 | 内容 |
|---|---|
tree-component.md |
avue-tree完整API:Option属性(12个)、Props属性(4个)、事件(7个)、方法(18个)、插槽(3个)、多选/懒加载/拖拽/虚拟模式示例 |
data-display.md |
23个数据展示组件列表、avue-data-display核心组件属性和数据结构 |
other-components.md |
22个独立组件:Card、DialogForm、Tabs、Search、Calendar、Flow、Login、Article、Chat、CountUp、Clipboard、Draggable、TextEllipsis、Sign、Print、Export、ImagePreview、Contextmenu、Video、Verify、Screenshot、License |
工作原理
主入口 SKILL.md(< 200行)始终加载到上下文中,提供:
- 快速安装指南
- 参考文件导航表(根据任务类型指引读取哪个文件)
- 代码生成核心规则
- 字段类型速查表
参考文件 按需加载,当用户需要特定组件的配置时才读取对应文件:
- 需要创建 CRUD 页面 → 读取
crud-core.md+crud-column.md - 需要配置搜索 → 读取
crud-search.md - 需要特定字段类型 → 读取
form-field-types.md - 需要文件上传 → 读取
form-advanced.md
- 需要创建 CRUD 页面 → 读取
双API风格 支持:
- Composition API(推荐):
<script setup>+ref()+ 箭头函数 - Options API:
export default+data()+methods
- Composition API(推荐):
数据来源
基于以下 Avue 官方文档与源码完整解析:
crud/目录 32 个文档(CRUD表格组件)form/目录 38 个文档(表单组件)component/目录 20 个文档(独立组件)default/目录 25 个文档(默认组件)data/目录 23 个文档(数据展示组件)docs/目录 10 个文档(全局配置、API、安装等)- Saber3 项目参考文件(Composition API vs Options API 对照)
- Avue v3.8.2 完整源码审计(packages/element-plus/ 全部组件 + packages/core/ 核心模块 + src/ 工具库)
总计 6,000+ 行 参考文档,覆盖 Avue v3.8.2 全部组件配置。
版本信息
- Avue 版本:v3.8.2 (2026-03-27)
- Vue 版本:Vue 3
- UI 框架:Element-Plus
- 创建日期:2026-04-05
Overview (`.claude/skills/blade-commit/README.md`)
Blade Commit
通用 Git 提交工具,基于 Gitmoji 规范生成风格统一的提交信息。
快速开始
# 简单模式(默认)— 单行 gitmoji + 描述
/blade-commit
# 详细模式 — gitmoji + conventional commit + 变更列表
/blade-commit -d
# 自定义信息 — 自动补全 gitmoji 格式
/blade-commit -m "新增接口权限模块"两种模式
简单模式(默认)
单行格式,适用于日常小改动:
:sparkles: 新增角色授权接口
:bug: 修复用户分页查询未过滤已删除数据
:zap: 优化字典查询排序逻辑详细模式(`-d`)
多行格式,适用于涉及多文件的较大提交:
:sparkles: feat(system): 新增接口权限模块
- 新增 ApiScope 实体与对应 Mapper / Service / Controller
- 新增 ApiScopeHandler 处理端点级权限过滤
- 在 RoleController 中追加接口权限授权接口常用 Gitmoji
| Gitmoji | 图标 | 场景 |
|---|---|---|
:sparkles: |
✨ | 新增功能 |
:bug: |
🐛 | 修复 Bug |
:zap: |
⚡ | 性能优化 |
:recycle: |
♻️ | 重构 |
:memo: |
📝 | 文档变更 |
:wrench: |
🔧 | 配置变更 |
:fire: |
🔥 | 移除代码 |
:tada: |
🎉 | 发布版本 |
:white_check_mark: |
✅ | 测试 |
:lock: |
🔒 | 安全修复 |
完整对照表见 SKILL.md。
安全保障
- 只做 commit,禁止 push、pull 等任何远程操作
- 零署名,不添加任何 AI/工具署名
- 逐文件暂存,不使用
git add .,排除敏感文件 - 自动适配,根据项目历史提交记录匹配语言和风格
Overview (`.claude/skills/blade-design/README.md`)
blade-design - SpringBlade 全栈代码生成器
基于 SpringBlade 开源版框架规范的智能代码生成 Skill,覆盖后端、前端、数据库三层,支持 Boot 单体和 Cloud 微服务两种架构模式。
功能概览
blade-design
├── 后端子技能 (backend)
│ ├── Entity / DTO / VO / Excel ← 数据模型层
│ ├── Mapper / Mapper.xml ← 数据访问层
│ ├── Service / ServiceImpl ← 业务逻辑层
│ ├── Controller ← 接口控制层
│ ├── Wrapper ← 数据转换层
│ └── Feign Client (Cloud) ← 微服务通信层
│
├── 前端子技能 (frontend)
│ ├── API 模块 ← Axios 请求封装
│ ├── Option 配置 ← Avue CRUD 列/表单配置
│ └── Vue 页面 ← Options API / Composition API
│
└── 数据库子技能 (database)
├── MySQL 建表 SQL ← 开源版官方支持方言
└── 菜单 SQL ← 权限菜单数据支持的架构模式
Boot 单体架构
- 所有代码在同一模块内
- 包名:
org.springblade.modules.{module} - Controller 路由含服务名前缀:
AppConstant.APPLICATION_XXX_NAME + "/path" - 无 Feign Client
Cloud 微服务架构
- API 模块(契约)与 Service 模块(实现)分离
- 包名:
org.springblade.{module} - Controller 路由无前缀(Gateway 自动路由)
- 含 Feign Client 接口 + 实现
支持的实体模式
| 模式 | 基类 | 适用场景 | 审计字段 | 租户隔离 |
|---|---|---|---|---|
| tenant | TenantEntity |
多租户业务表 | 自动继承 | 有 |
| base | BaseEntity |
跨租户业务表 | 自动继承 | 无 |
| raw | Serializable |
系统 / 关系表 | 手动定义 | 无 |
支持的数据库
SpringBlade 开源版仅官方支持 MySQL,建表脚本固定输出 MySQL 方言。
| 方言 | 引号 | 大小写 | 注释方式 | 引擎 |
|---|---|---|---|---|
| MySQL | ` |
小写 | COMMENT 内联 |
InnoDB + utf8mb4 |
支持的前端风格
| 风格 | 说明 | 适用场景 |
|---|---|---|
| Options API | Vue 3 传统选项式写法 | 与现有代码保持一致 |
| Composition API | Vue 3 组合式 <script setup> |
新功能开发推荐 |
支持的模板类型
| 类型 | 说明 | 适用场景 |
|---|---|---|
| crud | 标准增删改查 | 通用业务管理 |
| tree | 树形结构 CRUD | 分类、部门、菜单等层级数据 |
| sub | 主子表 CRUD | 订单-订单项、合同-条款等主从关系 |
使用方式
快速开始
帮我生成一个订单管理模块的代码指定参数
帮我生成一个产品管理的 CRUD:
- 模块名:product
- 实体名:Product
- 架构:boot
- 字段:
- productName (String) 产品名称,必填,搜索
- category (Integer) 产品分类,字典 product_category
- price (BigDecimal) 单价
- description (String/text) 产品描述
- status (Integer) 上架状态仅生成部分
帮我生成 Order 的建表语句(MySQL)
帮我生成前端页面,用 Composition API
只需要后端代码,Cloud 架构文件结构
blade-design/
├── SKILL.md ← 主技能文件(路由、配置、工作流)
├── README.md ← 本文档
└── references/
├── backend.md ← 后端代码模板(Entity/DTO/VO/Mapper/Service/Controller/Wrapper/Feign)
├── frontend.md ← 前端代码模板(API/Option/Vue 页面)
└── database.md ← MySQL 建表模板 + 菜单 SQLBoot vs Cloud 核心差异速查
| 维度 | Boot | Cloud |
|---|---|---|
| 基础包名 | org.springblade.modules.{module} |
org.springblade.{module} |
| Controller 路由 | AppConstant.APPLICATION_XXX_NAME + "/path" |
"/path" |
| Entity 位置 | 同模块 | API 模块 |
| 服务间调用 | 直接注入 | Feign Client |
| Feign Client | 无 | 接口在 API 模块,实现在 Service 模块 |
| POM 结构 | 单一 pom.xml | API + Service 各一个 |
| 服务注册 | 不需要 | Nacos |
| 网关路由 | 不需要 | Spring Cloud Gateway |
代码规范要点
- Long 类型 ID 必须
@JsonSerialize(using = ToStringSerializer.class)防精度丢失 - Date 字段同时添加
@DateTimeFormat和@JsonFormat - 逻辑删除字段
isDeleted添加@TableLogic(基类自动处理) - Swagger 使用 OpenAPI 3 注解(
@Tag/@Operation/@Schema/@Parameter),控制器类级标注无参@ApiOrder排序 - 响应统一使用
R<T>包装 - Wrapper 中通过
DictCache.getValue()翻译字典字段 - 前端权限标识格式:
{modelCode}_{action} - 表名统一
blade_前缀 - 主键使用雪花算法(ASSIGN_ID)
- 所有表包含标准审计字段
- Entity 类名不带
Entity后缀(如User而非UserEntity) - 权限控制使用
@PreAuth(RoleConstant.HAS_ROLE_ADMIN),开源版仅支持角色级权限
Overview (`.claude/skills/blade-plan/README.md`)
Blade Plan
SpringBlade 轻量规划执行工作流。将中等复杂度需求快速拆解为结构化任务,逐个执行,全程无辅助文件。
核心理念
先想清楚,再动手写。 面对涉及多个文件的改动,不急着写代码,而是先理清思路、拆好任务、确认方案,再逐个执行。用最小的流程开销,获得结构化开发的核心收益。
需求 → 分析规划 → 确认 → 逐任务执行 → 完成总结快速开始
# 启动规划执行 — 展示方案后等待确认
/blade-plan 给 blade-starter-redis 新增分布式限流注解,支持按IP和用户维度限流
# 自动模式 — 展示方案后直接执行,不等待确认
/blade-plan --auto 重构 OssTemplate,将各厂商实现拆分为独立策略类工作流程
交互模式(默认): 展示规划方案后暂停等待确认,审批通过后开始逐任务执行。
┌─────────────────────────────────────────────────────────────┐
│ │
│ 📋 分析与规划 │
│ 理解需求 → 扫描代码 → 制定方案 → 拆解任务 │
│ ↓ 用户确认 │
│ │
│ 🔨 逐任务执行(TaskCreate/TaskUpdate 追踪进度) │
│ Task 1 ✅ → Task 2 ✅ → Task 3 🔄 → Task 4 ⏳ → ... │
│ ↓ │
│ ✅ 完成总结 │
│ │
└─────────────────────────────────────────────────────────────┘自动模式(--auto): 展示规划后直接开始执行,不等待确认。
┌─────────────────────────────────────────────────────────────┐
│ │
│ 📋 分析规划 → 🔨 逐任务执行 → ✅ 完成总结 │
│ (展示方案后直接执行,不暂停) │
│ │
└─────────────────────────────────────────────────────────────┘适用场景
| 场景 | 适合 | 不适合 |
|---|---|---|
| 新增中等功能模块(如限流注解、审计日志) | ✅ | |
| 跨多个文件的 Bug 修复 | ✅ | |
| 模块级重构(如拆分策略类) | ✅ | |
| 新增 Starter 模块 | ✅ | |
| 现有功能增强(添加新维度、新策略) | ✅ | |
| 单文件简单修改 | ❌ 直接对话即可 | |
| 快速问答或查询 | ❌ 直接对话即可 | |
| 从零开发完整业务系统 | ❌ 建议拆成多次会话分阶段推进 | |
| 需要先独立设计数据模型或跨服务契约 | ❌ 先单独设计再进入 Plan |
复杂度分层
| 复杂度 | 文件变更量 | 建议方式 |
|---|---|---|
| 低 | 1~5 个文件 | 直接对话 |
| 中 | 5~15 个文件 | Blade Plan |
| 高 | 15+ 个文件 | 拆成多次会话,每次走一次 /blade-plan |
特性
- 零文件开销:不生成任何辅助文件,规划在对话中展示,进度由内置任务系统追踪
- 上下文锚定:每个任务执行前重读相关代码,防止偏离
- 构建验证:每组任务完成后自动执行编译检查
- 技能协同:自动识别可借助
/blade-design、/avue-design加速的任务 - 智能降级:过于简单时直接执行,复杂度过高时建议拆成多次会话
- SpringBlade 体系适配:内置 Boot / Cloud 分层最佳实践,同时可适配其他技术栈
文件结构
blade-plan/ # Skill 定义
├── README.md # 本文件
└── SKILL.md # Skill 主指令(全部内容,无 references 目录)运行时不产生任何文件,所有状态由 Claude Code 内置任务系统管理。
Doc Guide SpringCloud 5.0升级适配指南 (`doc/guide/SpringCloud-5.0升级适配指南.md`)
SpringBlade Cloud(微服务版)Spring Boot 4 升级适配指南
适用工程:
SpringBlade(Cloud 微服务版,23 模块:blade-gateway / blade-auth / blade-ops / blade-service / blade-service-api / blade-common)
依赖基座:blade-tool已升级到 Spring Boot 4.1.0 / Spring Cloud 2025.1.2 并发布为5.0.0
文档性质:升级指导 / 迁移规范。既供工程师直接阅读执行,也供 AI 依此拆解任务、逐文件推进迁移。
0. 核心前提:版本继承自 blade-tool
Cloud 工程通过 blade-core-bom 继承 blade-tool 的全套版本管理。因此升级的主杠杆只有一个:把 blade.tool.version 指向已升级的 blade-tool。Spring Boot 4.1.0 / Spring Cloud 2025.1.2 / Jackson 2 降级 / Web 容器 / 全局异常等框架级适配全部由 blade-tool 承担,Cloud 工程只需处理:
- 版本号与自身直接依赖(dynamic-datasource、maven 插件)
- 网关(WebFlux 容器 + 反应式错误处理 + 去 knife4j 聚合)
- MyBatis-Plus
IService/ServiceImpl包迁移(业务代码) - Knife4j 彻底移除(依赖 + 配置 + 注解)
⚠️ 前置动作:先在 blade-tool 工程执行
mvn clean install,把5.0.0装到本地/私服,Cloud 才能拉到升级后的基座。
1. 根 POM(`pom.xml`)
1.1 版本号指向升级后的 blade-tool
<blade.tool.version>4.10.0</blade.tool.version>
<blade.tool.version>5.0.0</blade.tool.version>1.2 dynamic-datasource 换 Boot4 版
dependencyManagement 里:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot4-starter</artifactId>
<version>4.5.0</version>
</dependency>若
dynamic-datasource-spring-boot3-starter还散落在子模块(如blade-demo)pom 里,一并改名。
1.3 spring-boot-maven-plugin 升到 Boot4
pluginManagement 里写死的插件版本必须升,否则可执行模块 repackage 阶段会用 Boot3 插件打包 Boot4 应用而失败:
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.2.10</version>
<version>4.1.0</version>2. 网关(blade-gateway)
网关是 WebFlux 反应式应用,Boot4 下有四处必改。
2.1 容器排除项修正(`blade-gateway/pom.xml`)
blade-tool 已把默认 Servlet 容器从 spring-boot-starter-web 换成 spring-boot-starter-webmvc。网关原先排除的是 spring-boot-starter-web + 已下线的 spring-boot-starter-undertow,升级后排除目标要改成 spring-boot-starter-webmvc,否则会把 Servlet 容器带进反应式网关:
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-launch</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-launch</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</exclusion>
</exclusions>
</dependency>
spring-cloud-starter-gateway-server-webflux(SCG 2025.1 的网关坐标)保持不变。
2.2 反应式错误处理器迁包(`handler/ErrorExceptionHandler.java`)
Boot4 把 WebFlux 错误处理类从 web.reactive.error 迁到了 webflux.error:
// 改前
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
// 改后
import org.springframework.boot.webflux.error.ErrorWebExceptionHandler;2.3 删除 Knife4j 网关聚合(见第 4 节;替代的自研 springdoc 聚合见 §2.5)
2.4 网关补 `com.fasterxml` ObjectMapper Bean(否则启动失败)
背景:Boot 4 默认 JSON 底座切到 Jackson 3(tools.jackson),com.fasterxml.jackson.databind.ObjectMapper 这个 Bean 在 Boot 4 里只由 spring-boot-jackson2 的自动配置提供。servlet 侧微服务经 blade-core-tool 带了 spring-boot-jackson2,不受影响;但网关排除了 servlet 栈、也不含 blade-core-tool,上下文里没有 com.fasterxml ObjectMapper Bean。而 AuthFilter / ErrorExceptionHandler 以构造注入方式依赖它写 JSON 响应 → 启动即抛 NoSuchBeanDefinitionException。SB3 能跑只因当年 Boot 默认自建了该 Bean,SB4 默认切 Jackson 3 后消失。
改法:网关内显式提供该 Bean(不引 spring-boot-jackson2,以免其 Jackson 2 编解码器干扰 WebFlux 默认的 Jackson 3 编解码):
// blade-gateway/src/main/java/org/springblade/gateway/config/JacksonConfiguration.java(新增)
@Configuration(proxyBeanMethods = false)
public class JacksonConfiguration {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}⚠️ 极隐蔽:缺的是 Bean(容器里没有
com.fasterxml的ObjectMapper)而非类,故编译通过、运行期启动失败。网关是三工程里唯一的反应式应用,其他 servlet 微服务不受影响。配套:
blade-gateway/pom.xml显式声明com.fasterxml.jackson.core:jackson-databind(版本由 BOM 托管),使该 ObjectMapper 的 Jackson 2 依赖成为一等声明,不再仅由jjwt-jackson间接传递而随其依赖图漂移。
2.5 网关接口文档聚合(自研:springdoc + Nacos 自动发现)
§4.1 删掉 knife4j 网关聚合后,网关文档门户由自研的 springdoc 聚合替代:从 Nacos 拉取在册服务,动态生成 Swagger-UI 下拉聚合,无需手工维护 urls。
① blade-gateway/pom.xml 加反应式 UI(版本由 BOM 托管 3.0.3,必须 webflux-ui、不能 webmvc-ui):
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
</dependency>② 新增两个类:
props/SwaggerDiscoveryProperties.java(@ConfigurationProperties("blade.swagger.discovery")):apiDocsPath默认/v3/api-docs、refreshInterval默认 30000、excludedServices默认排除blade-gateway/blade-admin/blade-log(共 3 项,勿漏blade-log,否则其文档会默认出现在聚合下拉里)。config/SwaggerAggregationConfiguration.java:注入ReactiveDiscoveryClient(Nacos 反应式,getServices()已subscribeOn(boundedElastic),不阻塞网关事件循环)与单例SwaggerUiConfigProperties;ApplicationReadyEvent首刷 +@Scheduled定时刷;每个服务拼new SwaggerUrl(id, "/" + id + "/v3/api-docs", id),整表setUrls(新 Set)原子替换(读侧每请求取快照,规避就地增删的并发修改)。
③ 放行(provider/AuthProvider.java):DEFAULT_SKIP_URL 新增 /*/v3/api-docs/**——各服务文档经网关同源路由 /{serviceId}/v3/api-docs 取回,需匿名可达。
④ 配置(application.yml / Nacos blade.yaml):
springdoc.api-docs.enabled: true——必须开启,关闭会连锁禁用聚合所依赖的SwaggerUiConfigProperties。springdoc.swagger-ui.disable-swagger-default-url: true——去掉默认 petstore 项。blade.swagger.discovery.excluded-services——排除网关自身、监控等无业务文档的服务。
⑤ 前置:网关须开启 spring.cloud.gateway.server.webflux.discovery.locator.enabled: true,由服务发现自动生成 /{serviceId}/** 路由,聚合 url /{serviceId}/v3/api-docs 才能转发到对应服务(此即已删 knife4j 聚合当年依赖的同一开关)。各微服务经 blade-tool 的 webmvc-ui 暴露 /v3/api-docs,SecureRegistry 默认已放行 /v3/api-docs/**。
机制:springdoc 的
/v3/api-docs/swagger-config端点每次请求都会重新拷贝单例SwaggerUiConfigProperties的 urls,故定时刷新时整表替换即在下一次拉取生效,无需重启。仅当控制器用带 description 的@Tag时其分组才进顶层 tags(与 blade-tool 指南 §9⑧ @ApiOrder 的分组排序相关)。
3. MyBatis-Plus `IService`/`ServiceImpl` 包迁移(业务代码)
MyBatis-Plus 3.5.17 把 IService/ServiceImpl 从 com.baomidou.mybatisplus.extension.service.* 迁到了 com.baomidou.mybatisplus.spring.service.*(该迁移为 3.5.17 的破坏性变更,3.5.16 仍在旧 extension.service 包)。Cloud 工程业务 Service 层大量继承它们,须全量改 import:
// 改前
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 改后
import com.baomidou.mybatisplus.spring.service.IService;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;批量替换命令(macOS):
find . -name '*.java' -not -path '*/target/*' -exec sed -i '' \
's#com\.baomidou\.mybatisplus\.extension\.service\.#com.baomidou.mybatisplus.spring.service.#g' {} +
com.baomidou.mybatisplus.extension.plugins.*(分页/租户/拦截器)未迁包,不要动。
4. Knife4j 彻底移除
Knife4j 无 Boot4 版本,依赖、配置、注解全部删除,改用 blade-tool 已内置的 springdoc 3.0.3。
4.1 网关聚合依赖与配置
blade-gateway/pom.xml:删除com.github.xiaoymin:knife4j-gateway-spring-boot-starter依赖。- 删除
blade-gateway/.../config/ReactiveDiscoveryConfiguration.java(该类只为 knife4j 文档聚合服务,依赖com.github.xiaoymin.knife4j.spring.gateway.*,无 knife4j 即无意义)。 blade-gateway/src/main/resources/application.yml:删除整段knife4j:网关聚合配置。filter/GatewayFilter.java:CORSALLOWED_HEADERS常量里去掉knfie4j-gateway-request、knife4j-gateway-code两个专供 knife4j 的请求头。
4.2 业务控制器注解
删除各控制器里的 @ApiOperationSupport(order = N) 注解及对应 import(Cloud 工程仅用到 @ApiOperationSupport,不涉及 @ApiSort):
// 删除 import
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
// 删除方法上的注解行
@ApiOperationSupport(order = 1)批量删除命令(macOS,注解均为单行):
find . -name '*.java' -not -path '*/target/*' -exec sed -i '' \
-e '/^[[:space:]]*import com\.github\.xiaoymin\.knife4j\.annotations\./d' \
-e '/^[[:space:]]*@ApiOperationSupport(/d' {} +不要引入
knife4j-annotations兼容包保留注解——这些注解在 springdoc 原生 UI 下不生效,属无效元数据。接口与分组排序改用 BladeX 的@ApiOrder(见 blade-tool 指南 §9⑧)。
⚠️ 上面的
find … '*.java'覆盖不到代码生成器模板:blade-ops/blade-develop/src/{main,test}/resources/templates/controller.java.vm里同样有@ApiOperationSupport的 import 与注解,须一并删除,否则该生成器产出的 Controller 引用已移除的 knife4j 包、编译不过。
✅ 删完 knife4j 排序注解后须补
@ApiOrder:仅删不补会让接口在 springdoc 原生 UI 下按字母序、丢失原有顺序。本次统一在每个带@Tag的控制器(23 处,含OssEndpoint及blade-demo示例)@Tag上方加一行无参@ApiOrder(importorg.springblade.core.swagger.annotation.ApiOrder),分组内接口即回落到源码声明顺序;方法体保留@Operation即可,无需逐个标@ApiOrder(n)。代码生成器模板controller.java.vm(main/test 两份)同样在@Tag上方补@ApiOrder。机制与「方法级精确覆盖」用法详见 blade-tool 指南 §9⑧。
4.3 Nacos 配置模板
doc/nacos/blade.yaml 里的 knife4j: 段一并删除(Nacos 上已下发的对应配置也需同步清理)。
4.4 springdoc 放行与接口文档入口
去掉 knife4j、改用 springdoc 原生 UI 后,需放行其静态资源与规格端点,并更新数据库里的接口文档菜单地址:
- 网关放行(
blade-gateway/.../provider/AuthProvider.java):DEFAULT_SKIP_URL新增/swagger-ui/**与/swagger-ui.html(springdoc UI 静态资源与其跳转入口);/v3/api-docs/**原已在放行清单,仅调整了位置。 - 接口文档菜单(
doc/sql/blade/blade.mysql.all.create.sql):blade_menu里「接口文档」菜单地址由http://localhost/doc.html改为http://localhost/swagger-ui.html;已初始化的库执行升级脚本doc/sql/blade/blade.mysql.upgrade.4.10.0.to.5.0.0.sql(内含该UPDATE,以旧值为条件、可重复执行)。
5. 容器与 Feign 配置适配
5.1 Undertow → Tomcat(自身 yml)
Boot 4 移除了 Undertow(详见 blade-tool 指南 §6),本工程自己的 yml 里若有 server.undertow.*,须换成 server.tomcat.*,否则是被忽略的死配置、原线程调优静默失效。涉及 blade-ops/blade-admin/…/bootstrap.yml 与 doc/nacos/blade.yaml(Nacos 共享模板):
# 改前
server:
undertow:
threads:
io: 16
worker: 400
# 改后(buffer/io 无 Tomcat 对应项:worker→threads.max、io→threads.min-spare)
server:
tomcat:
# 线程配置
threads:
# 最大工作线程数(可同时处理请求的线程上限)
max: 400
# 最小空闲工作线程数(保持存活的常驻线程数)
min-spare: 165.2 OpenFeign 5.x 失效配置清理
Cloud 2025.1 的 OpenFeign 升到 5.x:feign.* 前缀早已迁到 spring.cloud.openfeign.*,且 OkHttp 支持被整体移除。doc/nacos/blade.yaml 里的 feign.okhttp.enabled / feign.httpclient.enabled 已是静默无效的死配置,删除即可(保留仍有效的 feign.sentinel.enabled);Nacos 服务端已下发的对应配置也需同步清理。
blade-core-cloud里的io.github.openfeign:feign-okhttp依赖在 OpenFeign 5.x 下已无自动装配、成为孤儿,可按需清理(非必须,不影响运行)。
5.3 Servlet 编码前缀迁移(排查项)
Boot 4.0 把 Servlet 编码属性从 server.servlet.encoding.* 迁到 spring.servlet.encoding.*(元数据 level: error,硬迁移,旧键失效;详见 blade-tool 指南 §6④)。Cloud 各微服务及 Nacos 模板当前均未显式配置 Servlet 编码,依赖 Boot 默认(UTF-8),故本次无实际改动;后续若在任何 application.yml / Nacos 配置里新增编码项,须直接用新前缀:
spring:
servlet:
encoding:
charset: UTF-8
force: true5.4 Zipkin/Sleuth 残留清理(blade-common)
Sleuth/Zipkin 链路模型自 Boot 3 起已被 Micrometer Tracing 取代,spring.zipkin.* 命名空间在 SB4 / Cloud 2025.1 下已不存在。blade-common 一并清掉残留:
LauncherConstant.java:移除ZIPKIN_DEV_ADDR/ZIPKIN_PROD_ADDR/ZIPKIN_TEST_ADDR常量与zipkinAddr(profile)方法。LauncherServiceImpl.java:移除spring.zipkin.base-url属性注入(在新栈上为死配置)。
如需分布式链路追踪,改用 Micrometer Tracing(桥接 + OTLP/Zipkin 上报);此处为清理而非功能替换。
5.5 Nacos 3.2.2 镜像与配置适配(`script/docker/nacos/`)
nacos-client 由 blade-tool §11.1 主动锁定为 3.2.2(⚠️ 注:Spring Cloud Alibaba 2025.1.0.0 的 BOM 本身托管的是 nacos-client 3.1.1,3.2.2 是通过 alibaba.nacos.version 显式覆盖的,并非 Cloud 2025.1 自带),服务端镜像同步 v3.1.0 → v3.2.2(§8 已列)。但升级远不止改一个 tag:Nacos 3.2.x 引入了 AI 控制面(MCP / Skill / AgentSpec),会显著改变开箱行为,需配套处理以下几处。
① 镜像 tag(`script/docker/docker-compose.yml`)
# 改前
image: nacos/nacos-server:v3.1.0
# 改后(与 nacos-client 3.2.2 对齐)
image: nacos/nacos-server:v3.2.2② application.properties 必须替换为 3.2.2 官方版(`script/docker/nacos/conf/application.properties`)
背景:该文件经 volume 整体替换镜像内 /home/nacos/conf/application.properties。原挂载的是 Nacos 2.x 风格的精简配置(忽略路径还是 2.x 的 /console-fe/、缺 3.x 认证结构与 AI 开关),在 3.2.2 镜像上会丢失大量新默认值,并使 AI 模块按代码默认(开)运行。
改法:从 v3.2.2 镜像导出官方默认文件作为新模板,再追加 AI 关闭配置:
# 从运行中的 3.2.2 容器导出官方默认 application.properties(319 行)
docker exec <nacos容器> cat /home/nacos/conf/application.properties > application.properties数据源与认证的环境变量名(
MYSQL_SERVICE_*/NACOS_AUTH_*)在 3.2.2 官方默认文件里保持一致,compose 既有 env 无需改动。
③ 关闭 AI 发布流水线——否则控制台自动出现数千条配置(核心坑)
现象:v3.2.2 镜像自带 skills-data.zip(~7.6MB)+ agentspec-data.zip,由默认开启的 nacos.plugin.ai-pipeline / skill-scanner 在启动时解包灌入配置中心,控制台配置列表瞬间多出数千条。这不是联网导入,而是镜像内置数据;单机 Derby 下表现为「每次启动重新生成」,删容器重建也不消失。
关键:3.2.2 镜像启动参数为 --spring.config.additional-location=file:/home/nacos/conf/ + --spring.config.name=application,只加载 /home/nacos/conf/application.properties;2.x 的 /home/nacos/init.d/custom.properties 覆盖机制在该镜像已失效,挂了也不读。因此关闭开关必须写进 application.properties:
# 关闭 AI 发布流水线:阻止解包加载内置 skills-data.zip / agentspec-data.zip
nacos.plugin.ai-pipeline.enabled=${NACOS_AI_PIPELINE_ENABLED:false}
nacos.plugin.ai-pipeline.skill-scanner.enabled=${NACOS_AI_PIPELINE_SKILL_SCANNER_ENABLED:false}
# 关闭 AI 模块总开关:隐藏控制台 AI 菜单及相关 API
nacos.extension.ai.enabled=${NACOS_EXTENSION_AI_ENABLED:false}
nacos.plugin.ai.importer.mcp.official.*等联网导入器属性在该镜像默认文件里并不存在,真正的开关是上面的ai-pipeline/skill-scanner;nacos.istio.mcp.server.enabled/nacos.k8s.sync.enabled官方默认已是false,无需重复。
④ 鉴权 token 必须填写(`NACOS_AUTH_TOKEN`)
3.x 开启鉴权后,NACOS_AUTH_TOKEN 必须是 Base64 编码、≥32 字节的密钥,空值会导致启动失败。compose 模板保留空占位(供部署方自填),但部署前必须填写:
openssl rand -base64 32 # 生成合规密钥⑤ 数据持久化(推荐)
单机 Derby 数据默认在容器内,重建即丢。compose 新增数据卷,deploy.sh 的 mount() 同步创建该目录:
# docker-compose.yml nacos.volumes 新增
- /docker/nacos/data:/home/nacos/data# deploy.sh mount() 新增
if test ! -d "/docker/nacos/data" ;then
mkdir -p /docker/nacos/data
fi空的 data 目录挂载还会遮蔽镜像自带的 AI zip,等于给「不加载数千条」上了第二道保险。首次启用持久化前须确保 data 目录为空,避免把旧脏数据带入。
⚠️ 部署注意(老环境更新)
deploy.sh mount() 对宿主机文件是「不存在才拷贝」(if test ! -f)。已部署过的机器上 /docker/nacos/conf/application.properties 已存在,deploy.sh mount 不会用新模板覆盖它。更新 nacos 配置须手动覆盖后重建容器:
cp nacos/conf/application.properties /docker/nacos/conf/application.properties
docker-compose rm -sf nacos && docker-compose up -d nacos5.6 Feign 接口统一 `/feign/client` 前缀 + 网关内部接口隔离
背景:Provider 以 @RestController implements IXxxClient 实现 Feign 接口后,这些方法即成为真实 HTTP 端点——持有合法令牌的外部请求可像调用普通 Controller 一样直接访问服务间接口。为把 Feign 接口收敛为「仅供服务间调用」,做两件事:① 所有 Feign 接口统一 /feign/client/<模块> 路径前缀;② 网关对外拦截 feign 保留段。二者配合即闭环:服务间调用经注册中心直连、不过网关,不受影响;外部流量只能经网关,命中保留段即拒。
① Feign 前缀统一
改各 IXxxClient 的 API_PREFIX 常量即可——Provider 控制器均以该常量(或其派生常量)拼接映射,改接口一处,Feign 客户端与服务端映射两端同步:
| 接口 | 改前 | 改后 |
|---|---|---|
ISysClient |
/sys |
/feign/client/system |
IUserClient |
/user |
/feign/client/user |
IDictClient |
/dict |
/feign/client/dict |
IDataScopeClient |
/client/data-scope |
/feign/client/data-scope |
IApiScopeClient |
/feign/client/api-scope |
已合规,免改 |
INoticeClient(desk) |
/dashboard |
/feign/client/notice |
INoticeClient(demo) |
/client |
/feign/client/notice |
IStorageClient(seata) |
/storage/deduct |
/feign/client/storage/deduct |
IStorageClient未用API_PREFIX常量、直接写在@GetMapping上,除接口外还需同步改blade-seata-storage的StorageController类级@RequestMapping("storage")→@RequestMapping("/feign/client/storage"),保持两端一致。同时删除网关
AuthProvider.DEFAULT_SKIP_URL中失效的/storage/deduct/**放行项:该端点改名后原放行已匹配不到;新路径/feign/client/storage/deduct由InnerFilter对外拦截、内部走服务间直连,无需网关放行(/order/create/**是订单服务对外入口、非 Feign 端点,保留)。
ILogClient的API_PREFIX定义在框架blade-tool内,本工程不可改;其日志上报端点前缀由框架侧统一收敛,不在本次范围。
② 网关内部接口隔离(网关侧原生增强)
- 新增
provider/RequestProvider.java:getOriginalRequestPath(exchange)取裁剪服务名前缀之前的原始rawPath(避免依赖裁剪结果),不解码、不含查询串,原样交由判定方处理。 - 新增
filter/InnerFilter.java(GlobalFilter,order -150):原始路径中存在连续的feign、client路径段即返回 403,与是否持有合法令牌无关。order 晚于RequestFilter(-1000)(以取到原始路径)、早于AuthFilter(-100)(被拒路径不做无谓鉴权)。
判定的核心原则是与下游容器映射前的路径归一化等价:容器在接口映射前会对路径做归一化与一次百分号解码,判定若停留在原始串的子串匹配,与容器的实际映射依据就存在差异。
/feign/client 由连续两段构成,判定依赖段间的相邻关系,而相邻关系对归一化的具体操作与执行顺序都敏感——任一环节与容器不一致,都可能被路径变形把两段撑开而失配。故归一化严格按容器顺序实现:切分 → 剥离矩阵参数 → 解码 → 再次切分 → 消解相对段,随后在归一化后的段列表上做连续段比对;编码非法时无法推断容器解码结果,从严拒绝。
单段保留段(仅判
feign)不依赖相邻关系,对归一化顺序完全免疫、实现也更短,但会把/feign/**整体变为内部专用命名空间。本工程选择保留两段前缀语义,相应地必须完整实现上述归一化;若后续调整该判定,须同步确认..消解与「剥离矩阵参数先于解码」两点不被简化掉。
本方案以网关路径隔离为准:全部 Feign 接口已统一落在
feign保留段下,网关对外拦截即可挡住所有经网关的外部访问,无需在接口上额外加注解或做请求头处理。其防护边界在网关入口——绕过网关、直连微服务实例的调用不在拦截范围,故仍以「微服务只部署在内网、对外仅暴露网关」为前提。因此凡是接受外部可控标识入参的 Feign 接口,服务侧仍必须自行做归属与租户校验,不可把网关拦截当作唯一防线;若要覆盖「直连微服务」场景的纵深防御,可另行在服务侧增加内部标记校验。
6. 编译验证
⚠️ 升级后
<java.version>为 21,构建需 JDK 21(JDK 17 会报invalid source release: 21)。
# 先确保 blade-tool 5.0.0 已 install
cd blade-tool && mvn clean install -DskipTests
# 再构建 Cloud(跳过 docker 镜像构建)
cd SpringBlade && mvn clean install -DskipTests -Dmaven.test.skip=true -Ddocker.skip=true通过标准:23 个模块全部 SUCCESS,可执行模块 repackage 成功。
7. 运行期验证要点(交由真实环境执行)
- 网关:反应式路由、鉴权过滤、跨域、限流(Sentinel)是否正常;springdoc 网关聚合文档(§2.5):访问
/swagger-ui.html,服务下拉应随服务上下线自动增减。 - 各微服务:MyBatis-Plus + dynamic-datasource 多数据源装配、分页/租户拦截器。
- blade-admin 监控控制台(Spring Boot Admin 4.1.1 server)与各服务的 admin client 上报。
- Nacos 配置拉取(bootstrap 模式)、服务注册发现。
- Swagger-UI 入口从
doc.html改为/swagger-ui.html。
8. 受影响清单速览
| 类别 | 位置 | 动作 |
|---|---|---|
| 版本 | 根 pom blade.tool.version |
4.10.0 → 5.0.0 |
| 依赖 | 根 pom dynamic-datasource | boot3-starter:4.3.1 → boot4-starter:4.5.0 |
| 插件 | 根 pom spring-boot-maven-plugin | 3.2.10 → 4.1.0 |
| 容器 | blade-gateway/pom.xml 排除项 | starter-web/undertow → starter-webmvc |
| 源码 | blade-gateway ErrorExceptionHandler | web.reactive.error → webflux.error |
| 删除 | blade-gateway ReactiveDiscoveryConfiguration.java | 整文件删除(knife4j 聚合) |
| 源码 | blade-gateway GatewayFilter | 去 knife4j CORS 头 |
| 配置 | blade-gateway application.yml / Nacos blade.yaml | 删 knife4j 段 |
| 容器 | blade-admin bootstrap.yml / Nacos blade.yaml | server.undertow.* → server.tomcat.* |
| 配置 | Nacos blade.yaml | 删 OpenFeign 5.x 失效的 feign.okhttp/httpclient 键 |
| 源码 | blade-common LauncherConstant/LauncherServiceImpl | 移除 Zipkin 地址常量 / zipkinAddr() / spring.zipkin.base-url 注入 |
| 业务 | 全部 Service(约 30 处,15 对接口 + 实现) | IService/ServiceImpl 迁 spring.service |
| 业务 | 全部 Controller(17 处) | 删 @ApiOperationSupport + import |
| 业务 | 全部带 @Tag 的控制器(23 处,含 blade-demo)+ controller.java.vm 模板 | @Tag 上方新增无参 @ApiOrder(类级,接口按源码声明序)+ import org.springblade.core.swagger.annotation.ApiOrder(见 §4.2、blade-tool 指南 §9⑧) |
| 注释 | Controller / Service / Mapper / ServiceImpl 方法注释 | 分层收敛:Controller 精简为摘要行、Service/Mapper 补全 @param/@return、ServiceImpl private 方法补全(规范与改造记录见 blade-tool 指南 §17) |
| 依赖 | blade-gateway/pom.xml | 删 knife4j-gateway-spring-boot-starter |
| 新增 | blade-gateway 文档聚合(pom webflux-ui + SwaggerAggregationConfiguration + SwaggerDiscoveryProperties + AuthProvider 放行 /*/v3/api-docs/**) |
Nacos 自动发现聚合 springdoc 文档(见 §2.5) |
| 空值注解 | blade-gateway GatewayFilter | org.springframework.lang → org.jspecify.annotations |
| 空值注解 | blade-gateway JwtCrypto | reactor.util.annotation → org.jspecify.annotations |
| 源码 | blade-gateway JacksonConfiguration | 新增 com.fasterxml ObjectMapper @Bean(见 §2.4) |
| 依赖 | blade-gateway/pom.xml | 显式声明 com.fasterxml jackson-databind(自建 ObjectMapper 所需) |
| 安全 | blade-gateway AuthProvider | 新增放行 /swagger-ui/、/swagger-ui.html(/v3/api-docs/ 原已放行,仅移位) |
| 数据 | doc/sql blade_menu 接口文档菜单 | http://localhost/doc.html → http://localhost/swagger-ui.html |
| 环境 | 根 pom java.version + README |
17 → 21(构建需 JDK 21) |
| 部署 | 9 个 Dockerfile 基础镜像(blade-auth、blade-gateway、blade-ops×4、blade-service×3) |
bladex/alpine-java:openjdk17_cn_slim → openjdk21_cn_slim(与 JDK 21 对齐;blade-auth 另含注释的阿里云备用镜像行 openjdk17_cn_slim 同步改 21) |
| 文档 | CLAUDE.md 开发规范 | 同步刷新:文档栈 Knife4j→springdoc、Controller 约定去 @ApiOperationSupport、去 OkHttp 提法、JDK/Java 17→21 |
| 插件 | 根 pom maven-compiler / flatten | 3.11.0→3.15.0 / 1.3.0→1.7.3 |
| 部署 | script/docker/docker-compose.yml nacos-server 镜像 |
v3.1.0 → v3.2.2(与 nacos-client 3.2.2 对齐,详见 §5.5) |
| 配置 | script/docker/nacos/conf/application.properties |
2.x 精简模板 → 3.2.2 官方默认 + AI 关闭配置(§5.5②③) |
| 配置 | 同上 AI 开关 | 新增 nacos.plugin.ai-pipeline.enabled / skill-scanner.enabled / nacos.extension.ai.enabled = false,消除数千条内置 AI 配置(§5.5③) |
| 部署 | script/docker/docker-compose.yml nacos.volumes |
新增 /docker/nacos/data 持久化 + application.properties 挂载改 :ro(§5.5⑤) |
| 部署 | script/docker/deploy.sh mount() |
新增创建 /docker/nacos/data 目录(§5.5⑤) |
| 业务 | 全部 Feign 接口 IXxxClient(7 个,IApiScopeClient 已合规免改)+ seata StorageController |
API_PREFIX 统一为 /feign/client/<模块>,Provider 映射随常量同步(§5.6①) |
| 新增 | blade-gateway provider/RequestProvider.java + filter/InnerFilter.java |
网关对外拦截含 feign 保留段的请求、返回 403;判定只认首段 feign,采用「解码 + 逐段精确比对」对齐容器归一化,杜绝 //、/./、;params、%编码 变形绕过(§5.6②) |
9. Spring 7 空值注解迁移(JSpecify)
本次已完成迁移(含其他库空值注解归一)。官方依据(弃用 javadoc 直指 JSpecify、Spring 博客建议全生态统一)见同目录
blade-tool-SpringBoot4-升级适配指南.md§15。
Spring 7 把 org.springframework.lang.@Nullable/@NonNull 标记为 @Deprecated(since=7.0)(未 forRemoval),官方转 JSpecify(org.jspecify.annotations.*,1.0.0 已随 spring-core 在 classpath,无需新增依赖);官方并建议 Reactor 等全生态统一到 JSpecify。
- Spring 弃用注解:
blade-gateway/.../filter/GatewayFilter.java(@NonNull于filter(...)入参)由org.springframework.lang.NonNull→org.jspecify.annotations.NonNull。 - 其他库归一:
blade-gateway/.../utils/JwtCrypto.java的reactor.util.annotation.Nullable(3 处:decryptToString返回值 / 入参)→org.jspecify.annotations.Nullable,与全生态统一。均为标量、无数组,不涉及 TYPE_USE 位移。 - 验证:Cloud 23 模块
mvn clean installBUILD SUCCESS;全工程空值注解仅存org.jspecify.annotations.*,零org.springframework.lang.*/reactor.util.annotation残留。完整方式与 TYPE_USE 细节见 blade-tool 指南 §15。
Doc Nacos Blade Demo Dev.Yaml (`doc/nacos/blade-demo-dev.yaml`)
#自定义配置
demo:
name: demo-name
#放行配置
blade:
secure:
skip-url:
- /demo/**
datasource:
demo:
master:
url: jdbc:mysql://localhost:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
slave:
url: jdbc:mysql://localhost:3306/blade_slave?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
Doc Nacos Blade Dev.Yaml (`doc/nacos/blade-dev.yaml`)
#spring配置
spring:
data:
redis:
##redis 单机环境配置
host: 127.0.0.1
port: 6379
password:
database: 0
ssl:
enabled: false
##redis 集群环境配置
#cluster:
# nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
# commandTimeout: 5000
#项目模块集中配置
blade:
#通用开发生产环境数据库地址(特殊情况可在对应的子工程里配置覆盖)
datasource:
dev:
url: jdbc:mysql://localhost:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
Doc Nacos Blade Prod.Yaml (`doc/nacos/blade-prod.yaml`)
#spring配置
spring:
data:
redis:
##redis 单机环境配置
host: 10.211.55.5
port: 3379
password:
database: 0
ssl:
enabled: false
##redis 集群环境配置
#cluster:
# nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
# commandTimeout: 5000
#项目模块集中配置
blade:
#通用开发生产环境数据库地址(特殊情况可在对应的子工程里配置覆盖)
datasource:
prod:
url: jdbc:mysql://10.211.55.5:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
Doc Nacos Blade Test.Yaml (`doc/nacos/blade-test.yaml`)
#spring配置
spring:
data:
redis:
##redis 单机环境配置
host: 10.211.55.5
port: 3379
password:
database: 0
ssl:
enabled: false
##redis 集群环境配置
#cluster:
# nodes: 127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
# commandTimeout: 5000
#项目模块集中配置
blade:
#通用开发生产环境数据库地址(特殊情况可在对应的子工程里配置覆盖)
datasource:
test:
url: jdbc:mysql://10.211.55.5:3306/blade?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
username: root
password: root
Doc Nacos Blade.Yaml (`doc/nacos/blade.yaml`)
#服务器配置
server:
tomcat:
# 线程配置
threads:
# 最大工作线程数(可同时处理请求的线程上限)
max: 400
# 最小空闲工作线程数(保持存活的常驻线程数)
min-spare: 16
#spring配置
spring:
cloud:
sentinel:
eager: true
devtools:
restart:
log-condition-evaluation-delta: false
livereload:
port: 23333
#feign配置
feign:
sentinel:
enabled: true
#对外暴露端口
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
#springdoc-openapi配置
springdoc:
default-flat-param-object: true
#swagger配置信息
swagger:
title: SpringBlade 接口文档系统
version: 5.0.2
license: Powered By SpringBlade
licenseUrl: https://bladex.cn
terms-of-service-url: https://bladex.cn
contact:
name: smallchill
email: [email protected]
url: https://gitee.com/smallc
#blade配置
blade:
auth:
#使用 @org.springblade.test.Sm2KeyGenerator 获取,用于国密sm2验签,需和前端保持一致
public-key: ${BLADE_OAUTH2_PUBLIC_KEY}
#使用 @org.springblade.test.Sm2KeyGenerator 获取,用于国密sm2解密,前端无需配置
private-key: ${BLADE_OAUTH2_PRIVATE_KEY}
token:
#使用 @org.springblade.test.SignKeyGenerator 获取
sign-key: ${BLADE_TOKEN_SIGN_KEY}
#使用 @org.springblade.test.SignKeyGenerator 获取
aes-key: ${BLADE_TOKEN_CRYPTO_KEY}
#jackson配置
jackson:
#null自动转空值
null-to-empty: true
#大数字自动转字符串
big-num-to-string: true
#支持text文本请求,与报文加密同时开启
support-text-plain: false
#视图配置
view:
#动态模式的默认视图
default-view: summary
#角色→视图映射
role-mapping:
administrator: administrator
admin: admin
user: detail
guest: summary
xss:
enabled: true
skip-url:
- /weixin
secure:
skip-url:
- /test/**
client:
- client-id: sword
path-patterns:
- /sword/**
- client-id: saber
path-patterns:
- /saber/**
tenant:
column: tenant_id
tables:
- blade_notice
--- METRICS ---
- Files Extracted: 14
- Estimated Token Budget: ~12504 tokens
- Canonical Reference: https://codewiki.google/github.com/chillzhuang/SpringBlade