今日日报:common-web 大重构 + R4 FallbackFactory 自动配置 + 技术枚举落地

今日工作 1. common-web 目录整理 + 注解化控制 common-web 之前的目录有点乱, @EnableXxx 注解和 @Configuration 配置类全混在 config/ 包里。今天拆了一刀: 改前: config/ EnableApiResultWrapper.java ← 注解 EnableRequestLogFilter.java ← 注解 ApiResultWrapperConfiguration.java RequestLogFilterConfiguration.java WebAutoConfiguration.java 改后: annotation/ ← 注解单独放 EnableApiResultWrapper.java EnableRequestLogFilter.java config/ ← 只放 @Configuration ApiResultWrapperConfiguration.java RequestLogFilterConfiguration.java WebAutoConfiguration.java 同时引入了 @EnableXxx 模式替代原本的 @ConditionalOnProperty : @EnableRequestLogFilter — 替代 3 个服务里重复的 RequestLogFilterConfig.java ( FilterRegistrationBean 配置完全相同,只是包名不同) @EnableApiResultWrapper — 控制 GlobalApiResultHandler 是否生效 2. GlobalApiResultHandler 失效之谜 GlobalApiResultHandler 实现了 ResponseBodyAdvice<Object> ,通过 WebAutoConfiguration#@Bean 注册。按理说 Spring MVC 会自动发现,但实际上没生效——所有 @RestController 的返回都是裸数据,没有被 ApiResult 包装。 ...

七月 1, 2023 · 3 分钟 · 477 字 · yaomingye

今日日报:Nacos 配置统一收敛 + FeignFallbackProxy 降级代理重构 + Resilience4j 落地

今日工作 1. FeignFallbackProxy:用动态代理干掉模板代码 昨天写了 8 个 FallbackFactory,每个 50+ 行,全是 return null / 空列表 / 0 的模板代码。今天抽了个 FeignFallbackProxy 到 common-core,基于 JDK 动态代理,根据方法返回类型自动推断兜底值。 // 改前:14 个方法逐个手写 return new UserFeignClient() { @Override public List<UserDTO> findByIds(List<Long> ids) { log.warn("[降级] findByIds 返回空列表"); return Collections.emptyList(); } // ... 每个方法都来一遍 }; // 改后:一行搞定 return FeignFallbackProxy.create(UserFeignClient.class, cause); 8 个工厂从 ~400 行缩到 ~40 行,核心逻辑全部收敛到 FeignFallbackProxy 一处。以后加新的 FeignClient 降级也只需要 5 行。 2. Nacos 配置统一收敛 之前每个服务在 Nacos 里都有一份独立的 yml,Redis 连接配了 8 遍、JWT 密钥配了 11 遍。花了半天把 common.yaml 重新扶正——所有共享配置(Redis、JWT、devtools、bean-override、Resilience4j)归到 common,各服务只留数据库、中间件等特有配置。 ...

六月 29, 2023 · 1 分钟 · 167 字 · yaomingye

今日日报:Admin 控制器合并、Swagger 描述优化、Feign 熔断降级体系搭建

今日工作 1. Admin 控制器合并重构 mall-admin 的 controller 层从 15 个砍到了 7 个。 删了 8 个——4 个 internal 控制器(UserInternalController、RoleInternalController、DeptInternalController、JobInternalController),4 个关联表控制器(UserRoleController、RoleMenuController、RoleDeptController、UserAvatarController)。 理由很简单:internal 控制器的方法本来就是对同一张表查数据,合并到 UserController、RoleController、JobController 就够了。关联表控制器纯 CRUD,也没人调,留它过年。 UserFeignClient 的请求路径也顺手从 /v1/internal/user/* 改到了 /v1/auth/user/*,因为 internal 路径已经不存在了。 2. Swagger 描述统一 之前 @Operation(summary = "通过id查询")、@Operation(description = "删除") 这种写了等于没写。 这次给 6 个 Controller 的每个接口都加了三段式描述——认证要求 + 参数说明 + 业务说明: 需 Bearer Token + admin 角色 | 查询参数:id(用户ID) 无需认证(公开接口)| 无参,返回全部角色列表 需 Bearer Token | 请求体:RoleConditionEntity(分页条件) 顺便把白名单逻辑的现状写进了 Security 注释,哪些接口免登录一目了然。 3. Feign 熔断降级体系 这是今天的大头。项目之前 Feign 调用异常处理几乎裸奔——FeignResultDecoder 的核心逻辑被人注释掉了,没有 ErrorDecoder、没有 FallbackFactory、没有断路器。 ...

六月 27, 2023 · 1 分钟 · 166 字 · yaomingye

全链路修复:微服务 JWT 鉴权踩坑记

今日工作 1. Nacos 配置 namespace 发现与修复 项目里 12 个微服务全部使用 Nacos 作为配置中心和注册中心,namespace 是 7af60364-xxx-xxx-xxx 的自定义空间,但之前某次推送配置时没指定 namespace,全部落到了 public 下。等于写了半天的配置全白干。 问题: 服务启动时就报数据库连接超时、Redis 连不上——因为在 public 命名空间下根本找不到 mall-admin-api-dev.yaml 这类配置。 修复: 确认各服务本地 application.yml 中的 spring.cloud.nacos.config.namespace 已正确指向目标命名空间。由用户在 Nacos 控制台手动导回配置。 同时发现 3 个服务(gateway、admin、customer)在本地 application.yml 中通过 shared-configs 引用了 common.yaml ,但该文件早已名存实亡、内容冲突(同一个 key 在 YAML 里出现两次,如 spring: 和 management: 各两遍)。直接移除 shared-configs 引用。 2. MyBatis mapper XML 加载失败 admin 服务调用 POST /v1/internal/user/testLogin 返回 {"code":1,"message":"用户名或密码错误"} ,但密码哈希确认没问题,数据库也查得到用户。查日志发现原因并非密码不匹配,而是 MyBatis mapper XML 文件根本未被加载。 // UserMapper 接口 package cn.net.mall.admin.mapper.auth; // 接口在 auth 包 // UserMapper.xml(XML 文件) // 实际路径: .../mapper/admin/UserMapper.xml // 文件在 admin 目录 接口包名是 auth ,XML 文件路径是 admin ——MyBatis 默认的 mapper-locations 是 classpath*:mapper/**/*.xml ,根本扫不到 cn/net/mall/... 路径下的文件。所有 mapper 方法调用都静默抛异常,被 testLogin 的 catch 块兜底包装为"用户名或密码错误",极具迷惑性。 ...

六月 25, 2023 · 4 分钟 · 772 字 · yaomingye

合并与修复:mall-common重构、Nacos恢复、中间件排查

今日工作 1. 外部 Starter 合并回 mall-common 之前将 mall-common 的基础设施拆分到了独立仓库 mall-spring-boot-starters (含 common-core 、 redis-starter 、 workid-starter 、 web-starter 、 sensitive-starter ),但独立维护成本高、构建链长、改个工具类要跨仓库发版。今日全部合并回主项目。 具体操作: 5 个 external starter 模块搬入主项目,改用主项目 parent POM mall-common-core 与 mall-common 去重(删除 14 个重复工具类,由 common-core 提供) Redisson 依赖彻底移除(零处使用,纯历史包袱) JJWT 统一为 0.12.6 拆分 artifacts,替代旧版合并 JAR 各服务 POM 去掉外部 starter 引用,改为本地模块依赖 2. Application 启动类命名统一 去除 Api 后缀,统一为 {模块名}Application (如 BasicApiApplication → BasicApplication );BFF 层加 Bff 后缀( AdminApiApplication → AdminBffApplication )。 影响范围: 8 个文件改名 + 对应 SpringApplication.run() 引用修复。 ...

六月 23, 2023 · 2 分钟 · 218 字 · yaomingye

今日日报:auth拆分、模块更名、RSA删除、全量编译

今日工作 1. auth 模块拆分与清理 mall-auth 服务整体删除:业务代码(用户管理/RBAC/收货地址)全部迁入 mall-admin ,仅 JWT + Redis 黑名单功能原属 auth,现已整合进 mall-admin mall-auth-client 删除:所有调用方(mall-basic、mall-marketing、mall-message、mall-product、mall-order、mall-order-client)依赖全部切换至 mall-admin-client mall-auth-api-starter 保留不动(AuthApiInterceptor + FeignAuthInterceptor 全项目在用) 2. 模块更名(四组) 原名 新名 说明 mall-admin-api mall-admin-bff BFF 聚合层 mall-mobile-api mall-mobile-bff BFF 聚合层 mall-member mall-customer C 端业务服务 mall-member-client mall-customer-client Feign 接口 对应 Nacos 注册名同步更新:mall-admin-bff, mall-mobile-bff, mall-customer-api Gateway 路由同步:新增 /api/customer/, /api/admin-api/, /api/admin/, /api/mobile/ 路由 Nacos 配置:新建 mall-customer-api-dev.yaml, mall-admin-api-dev.yaml,删除旧名配置 3. 删除 RSA 密码加密层 原登录流程:前端 JS RSA 加密 → 后端 RSA 私钥解密 → BCrypt 校验 ...

六月 21, 2023 · 1 分钟 · 123 字 · yaomingye

Maven Surefire 测试中的 MalformedInputException:当 JVM 默认编码与 Nacos 配置编码不一致时

又见编码问题:mvn test 报 MalformedInputException,IDE 却好好的 某开发者最近在项目中遇到一个奇怪的现象:mvn test 跑 Spring Boot 集成测试时,应用上下文启动失败,控制台抛出一串 MalformedInputException: Input length = 1。但同样的代码,在 IDE 里直接点"运行"按钮,启动得丝般顺滑。 这看起来像是 Nacos 配置中心的问题——因为错误信息里提到了 nacos:mall-auth-api-dev.yaml 配置文件找不到。但用 curl 请求 Nacos API,配置明明存在,内容也是合法的 YAML。 到底是哪里出了问题? 问题复现 执行命令: mvn test -pl mall-auth 控制台输出类似: *************************** APPLICATION FAILED TO START *************************** Description: Config data resource 'NacosConfigDataResource{...}' via location 'nacos:mall-auth-api-dev.yaml' does not exist 但此刻如果打开浏览器访问 Nacos 控制台,或者用 curl 直接拉取: curl "http://localhost:8848/nacos/v1/cs/configs?dataId=..." 配置内容完整返回,HTTP 状态码 200。所以配置是存在的,但 Nacos 客户端在 Spring Boot 中读取失败了。 翻到堆栈深处,真正的异常是: Caused by: org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1 at com.alibaba.cloud.nacos.parser.NacosDataParserHandler.parseNacosData(...) at com.alibaba.cloud.nacos.configdata.NacosConfigDataLoader.pullConfig(...) Caused by: java.nio.charset.MalformedInputException: Input length = 1 at java.base/java.nio.charset.CoderResult.throwException(...) at java.base/sun.nio.cs.StreamDecoder.implRead(...) 这就清楚了——不是配置"不存在",而是配置内容解析时遇到了字符编码问题。SnakeYAML 在读取 YAML 时,接收到了一个无法解码的字节序列。 ...

六月 19, 2023 · 4 分钟 · 726 字 · yaomingye

把 React + Vite 项目搬到 Electron 去:改造、踩坑与调试

把 React 项目搬到 Electron,顺便让 PDF 导出不再闹心 某开发者手头有个 Vite + React + TypeScript 的简历编辑器项目,浏览器里跑得好好的,但每次要导出 PDF 都得先开新窗口、再唤出浏览器打印对话框、再手动取消「页眉和页脚」——这套操作重复多了真的会烦躁。于是决定把它改成 Electron 桌面应用。 这篇文章记录了改造全过程,顺便解决了国内下载 Electron 二进制的问题,以及几个常用的调试命令。 第 1 步:先确认你从什么起点出发 这次改造的对象是一个标准的 Vite + React + TypeScript 前端项目,没有用任何奇怪的自定义配置。如果你也是类似的项目结构,可以直接照着操作。 改造前后的技术栈对比: 改造前 改造后 Vite 8 开发服务器 Vite 8 + Electron 43 React 18 + TypeScript 不变 MUI v9 组件库 不变 window.print() 导出 PDF webContents.printToPDF() 原生导出 浏览器 localStorage 持久化 不变 + 原生「另存为」对话框 验证入口: 项目根目录应该有一个 package.json,内含 "scripts": { "dev": "vite" },项目本身能通过 npm run dev 正常启动。 ...

四月 5, 2023 · 5 分钟 · 974 字 · yaomingye

今日日报:文档分组、接口聚合、配置扫描

今日日报 干了什么 Swagger 文档三层分组 给 8 个微服务分了三个文档组——前端接口、后台接口、内部微服务接口。加了 emoji 前缀区分,各服务不再相互干扰。所有内部接口统一加了 /v1/internal/ 路径前缀。 BFF 聚合 之前 BFF 层基本是透传,今天把管理后台的控制器补全了。系统管理、商品管理、订单管理、营销管理、基础数据都有了对应的 BFF 控制器和 Swagger 文档。小程序那边原本就做了首页和商品详情的聚合,今天补了用户中心。 前端接口映射 扫了两个前端项目(小程序和管理后台),列了 50 多个 API 调用,逐个去后端代码里 grep 确认接口路径。发现了 4 个前端写了但后端不存在的接口,也确认了一批属于另一个系统的接口。 DTO 注解补齐 一天下来给 103 个 DTO 和 Entity 加了 @Schema 注解,类级和字段级都有,Swagger 文档不再是黑盒了。 Nacos 扫描 拉到了全部 10 个服务的 Nacos 配置,更新了配置文档,补了 BFF 服务的 template 文件。 README 瘦身 把 README 里超长的内容拆到 docs 目录下,加了架构改进建议文档,整理了 28 项待改进问题。 明日计划 继续推进遗留任务。

三月 18, 2023 · 1 分钟 · 64 字 · yaomingye

微服务文档重构:API 分组、BFF 聚合与文档拆迁

今天干了啥:分组、聚合、拆文档 今天没写啥牛逼的业务代码,大部分时间在跟文档和接口结构较劲。记个流水账。 一、发现 doc.html 不对劲 打开一个微服务的 Knife4j 文档页,下拉框里赫然列着七八个其他服务的分组。一点就 404,明摆着是隔壁服务跑这儿串门了。 第一反应是 knife4j 的配置问题,加了一堆 enableXxx: false ,重启——纹丝不动。后来发现 knife4j 基础 starter 压根没有跨服务聚合功能。真正的原因藏在 SpringDoc 的配置链路里,某些共享配置文件往 swagger-config 端点的 urls 字段里塞了外部的分组 URL。 最后在每个服务的本地 application.yml 把 springdoc 配置全写死,用本地覆盖干掉了注入。顺便把相关的配置说明写进系统设计文档了。 产出: 一篇踩坑博客 + 配置修复。 二、给接口文档分了三个层 之前所有微服务的接口都在一个组里,前端要看、后端也要看、微服务 Feign 调用也混在一起。这次给每个服务分了三个 Swagger 分组: 前端接口(给前端的) 后台接口(给管理后台的) 内部接口(给其他微服务调用的) 每个服务各自独立,不再相互干扰。 三个分组的接口在代码上也做了物理隔离——新建了 controller/internal/ 包,只给微服务间 Feign 调用用。顺便把原来跟前端接口冲突的方法也挪过去了,URL 统一加 /v1/internal/ 前缀,从根上避免路由冲突。 三、把前端需要的接口聚合到 BFF 层 之前前端写个页面经常要调好几个微服务,商品详情页调了 5 次接口。虽然 BFF 层之前就已经做了一些聚合(首页聚合、商品详情聚合、下单预览聚合),但管理后台这边基本还是透传状态。 给管理后台 BFF 加了两个聚合接口: 用户编辑页:一次查出用户信息 + 角色列表 + 部门树 + 岗位列表 商品编辑页:一次查出商品详情 + 分类树(品牌和单位的数据等后续补 Feign 客户端) 同时给两个 BFF 服务都加上了 Swagger 文档。以后前端重写,只看这两个 BFF 的文档就够了,不用再翻 8 个微服务的接口。 ...

三月 16, 2023 · 1 分钟 · 127 字 · yaomingye
Cat Radio