diff --git a/README.md b/README.md
index 51f5076..80fc854 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
diff --git a/blade-core-boot/src/main/resources/bootstrap.yml b/blade-core-boot/src/main/resources/bootstrap.yml
index 3c0ebe1..e91fbd5 100644
--- a/blade-core-boot/src/main/resources/bootstrap.yml
+++ b/blade-core-boot/src/main/resources/bootstrap.yml
@@ -94,7 +94,7 @@ mybatis-plus:
swagger:
title: SpringBlade 接口文档系统
description: SpringBlade 接口文档系统
- version: 5.0.0
+ version: 5.0.1
license: Powered By SpringBlade
licenseUrl: https://bladex.vip
terms-of-service-url: https://bladex.vip
diff --git a/blade-core-cloud/pom.xml b/blade-core-cloud/pom.xml
index a839b97..4b7629d 100644
--- a/blade-core-cloud/pom.xml
+++ b/blade-core-cloud/pom.xml
@@ -41,6 +41,16 @@
org.springframework.cloud
spring-cloud-starter-bootstrap
+
+
+ tools.jackson.core
+ jackson-databind
+
de.codecentric
diff --git a/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/config/FeignJacksonEnvPostProcessor.java b/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/config/FeignJacksonEnvPostProcessor.java
new file mode 100644
index 0000000..360c8f6
--- /dev/null
+++ b/blade-starter-loadbalancer/src/main/java/org/springblade/core/loadbalancer/config/FeignJacksonEnvPostProcessor.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springblade.core.loadbalancer.config;
+
+import net.dreamlu.mica.auto.annotation.AutoEnvPostProcessor;
+import org.jspecify.annotations.NonNull;
+import org.springframework.boot.EnvironmentPostProcessor;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.env.DefaultPropertiesPropertySource;
+import org.springframework.core.Ordered;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.util.ClassUtils;
+
+import java.util.Map;
+
+/**
+ * Feign 分页模型 JSON 支持的装配兼容处理
+ *
+ *
+ * Feign 为 Spring Data 的分页与排序模型提供的两个 JSON 扩展仅有 Jackson 3 实现,
+ * 而其装配条件本应校验的 Jackson 模块基类在 Jackson 3 中已改名,上游条件退化为恒成立,
+ * 于是只要分页与排序模型在类路径上就会装配,Jackson 3 缺席时中断容器启动。
+ *
+ *
+ *
+ * 故仅在 Jackson 3 缺席时给出关闭的默认值,该默认值优先级最低,下游可显式开启;
+ * Jackson 3 在场时不再干预,交由上游条件判定。
+ *
+ *
+ * @author Chill
+ */
+@AutoEnvPostProcessor
+public class FeignJacksonEnvPostProcessor implements EnvironmentPostProcessor, Ordered {
+
+ /**
+ * Feign 分页模型 JSON 支持开关
+ */
+ private static final String FEIGN_JACKSON_KEY = "spring.cloud.openfeign.autoconfiguration.jackson.enabled";
+
+ /**
+ * Jackson 3 模块基类,上述两个扩展的直接父类
+ */
+ private static final String JACKSON_MODULE_CLASS = "tools.jackson.databind.JacksonModule";
+
+ @Override
+ public void postProcessEnvironment(@NonNull ConfigurableEnvironment environment, SpringApplication application) {
+ if (ClassUtils.isPresent(JACKSON_MODULE_CLASS, application.getClassLoader())) {
+ return;
+ }
+ Map defaults = Map.of(FEIGN_JACKSON_KEY, Boolean.FALSE.toString());
+ DefaultPropertiesPropertySource.addOrMerge(defaults, environment.getPropertySources());
+ }
+
+ @Override
+ public int getOrder() {
+ return Ordered.LOWEST_PRECEDENCE;
+ }
+
+}
diff --git a/doc/guide/blade-tool-5.0升级适配指南.md b/doc/guide/blade-tool-5.0升级适配指南.md
index c6fa771..ebee1db 100644
--- a/doc/guide/blade-tool-5.0升级适配指南.md
+++ b/doc/guide/blade-tool-5.0升级适配指南.md
@@ -348,7 +348,7 @@ public class JacksonConfiguration {
> ⚠️【务必看清,这是升级中最隐蔽的一个坑】Spring 7 的 `WebMvcConfigurationSupport.getMessageConverters()` 执行顺序是:先 `configureMessageConverters(list)` → 若 list 仍为空才 `addDefaultHttpMessageConverters(list)`(这一步才注册 ByteArray/String/Resource/ResourceRegion/Form 以及 JSON 转换器)→ 最后 `extendMessageConverters(list)`。
> 若重写 `configureMessageConverters` 并向 list 添加任何转换器,list 变为非空,`addDefaultHttpMessageConverters` 会被**整段跳过**,MVC 最终只剩下你加入的这一个转换器——文件下载、`byte[]`/图片/PDF、纯文本、表单请求体全部 406/`HttpMessageNotWritableException` 失败。**编译与纯 JSON 接口都正常,极难在冒烟测试中发现。**
-> 正解是重写 `extendMessageConverters`:它在默认列表构建完成之后回调,拿到的是**完整**的默认转换器,再原地替换 JSON(因 §5.5⑤ 已强制 `preferred-json-mapper=jackson2`,默认 JSON 转换器为 `MappingJackson2HttpMessageConverter`,属 `AbstractJackson2HttpMessageConverter`)与 String 转换器即可,其余转换器原样保留。
+> 正解是重写 `extendMessageConverters`:它在默认列表构建完成之后回调,拿到的是**完整**的默认转换器,再原地替换 JSON(因 §5.5⑤ 已在托管层剥离 Jackson 3,默认 JSON 转换器为 `MappingJackson2HttpMessageConverter`,属 `AbstractJackson2HttpMessageConverter`)与 String 转换器即可,其余转换器原样保留。
```java
@Override
@@ -387,7 +387,28 @@ public void extendMessageConverters(List> converters) {
> 与 Jackson 无关的 `org.springframework.lang.Nullable/NonNull` 在 Spring 7 也被弃用(官方推 JSpecify),那是一处独立、面广的迁移,不在本表范围,别混入 Jackson 的 `@SuppressWarnings`。
-**⑤ 【关键】强制 preferred-json-mapper = jackson2**——新增一个 `LauncherService`,否则 Boot 4 默认注册 Jackson 3 转换器,§5.5③ 的 `instanceof AbstractJackson2HttpMessageConverter` 命不中,Blade 的 JSON 处理静默失效:
+**⑤ 【关键】让 Boot 4 选中 Jackson 2**——Boot 的择一逻辑写在 `org.springframework.boot.http.converter.autoconfigure` 下,读源码可见是**两条并列通路,满足其一即可**(`Jackson2HttpMessageConvertersConfiguration.PreferJackson2OrJacksonUnavailableCondition` 是 `AnyNestedCondition`):
+
+```java
+// Jackson 3 分支——三个条件同时成立才注册(javap 实测 JacksonJsonHttpMessageConverterConfiguration)
+@ConditionalOnClass(tools.jackson.databind.json.JsonMapper.class)
+@ConditionalOnBean(tools.jackson.databind.json.JsonMapper.class) // ← 关键:要 Bean,不只是类
+@ConditionalOnProperty(name = "spring.http.converters.preferred-json-mapper",
+ havingValue = "jackson", matchIfMissing = true)
+
+// Jackson 2 分支——以下任一命中即生效
+@ConditionalOnProperty(name = "...preferred-json-mapper", havingValue = "jackson2") // 通路 A
+@ConditionalOnMissingBean(JacksonJsonHttpMessageConvertersCustomizer.class) // 通路 B
+```
+
+- **通路 B(主)**:Jackson 3 分支要的是**容器里有 `JsonMapper` Bean**,而该 Bean 只由 `spring-boot-jackson` 自动配置模块产出;托管层已把该模块摘掉(见 §5.5⑥),Bean 不存在 → Jackson 3 分支不命中 → Jackson 2 分支的 `@ConditionalOnMissingBean` 成立。这是**编译期事实**,不依赖启动路径。
+- **通路 A(兜底)**:`LauncherService` 设 `preferred-json-mapper=jackson2`,覆盖下游未继承 blade 托管层、`spring-boot-jackson` 漏进 classpath 的场景。
+
+> ⚠️ 别把「剥离 Jackson 3」理解成「classpath 上不能有 `tools.jackson`」——**决定管线的是 `JsonMapper` Bean 在不在,不是 Jackson 3 的类在不在**。Jackson 3 的库照常引入不会翻转管线,反而是必需的,理由见 §5.5⑧。
+
+> 两条都留的原因:通路 A 仅在 `BladeApplication` 启动路径执行,`@SpringBootTest`、blade-gateway(不含 blade-core-tool)覆盖不到;且 Jackson 3 的 **XML 转换器分支**(`JacksonXmlHttpMessageConverterConfiguration`)只有 `@ConditionalOnClass` + `@ConditionalOnBean`,**不受 `preferred-json-mapper` 约束**,属性通路结构性覆盖不到。
+>
+> 关于失效程度需说清:因 §5.5③ 的 `if (!jsonReplaced) converters.add(0, bladeJson)` 兜底,即使两条通路全漏、Jackson 3 转换器占位,blade 转换器仍会插到队首优先命中,**MVC 服务端不会失效**;真正会静默回落到 Jackson 3 的是 `RestClient`/`RestTemplate` 客户端转换器与 WebFlux 编解码器。
新增 `blade-core-tool/.../config/JacksonLauncherServiceImpl.java`:
@@ -408,6 +429,92 @@ public class JacksonLauncherServiceImpl implements LauncherService {
}
```
+**⑥ 【主通路】托管层剥离 Jackson 3 的自动配置模块(只剥模块,不剥库)**——在父 POM `dependencyManagement` 把 `spring-boot-jackson` 从传递链上摘掉,容器里便不会出现 `JsonMapper` Bean,§5.5⑤ 的通路 B 恒成立。**剥离对象仅限这个自动配置模块,`tools.jackson` 系的库本体照常引入**(理由见 §5.5⑧)。**需要两个条目,缺一不可**:
+
+```xml
+
+
+ org.springframework.boot
+ spring-boot-starter-jackson
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-jackson
+
+
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 3.0.3
+
+
+ org.springframework.boot
+ spring-boot-jackson
+
+
+
+```
+
+> ⚠️ 为什么 springdoc 必须单独排:`springdoc-openapi-starter-common:3.0.3` **直接依赖** `org.springframework.boot:spring-boot-jackson`,而不是经 `spring-boot-starter-jackson` 传递,上面第一个条目的 `` 只约束它自己的子树,管不到 springdoc。可用 `mvn dependency:tree` 单独验证(注意:在完整工程里跑,Maven 的 nearest-wins 会把 springdoc 分支下的重复节点省略,须用只含 springdoc 的最小 POM 或加 `-Dverbose` 才看得见)。
+>
+> springdoc 内部仅 Spring Data REST 支持类引用 Jackson 3,且被 `@ConditionalOnClass(RepositoryRestConfiguration)` 守卫,排除无副作用。
+>
+> 子模块**不需要**再写一遍局部 ``:子模块继承父 `dependencyManagement`,下游工程经 `blade-core-bom` 展开同样继承,重复声明纯属冗余。
+
+**⑦ 序列化管线门禁**——托管层排除是"当前依赖树"的快照,第三方库升级随时可能开出新的引入路径(springdoc 直连就是活例)。父 POM `` 挂一条 enforcer 规则,把漏排从**运行期静默回落**提前成**构建期失败**,并顺带校验托管层排除是否随 `blade-core-bom` 正确传导:
+
+```xml
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven.enforcer.version}
+
+
+ ban-jackson3-autoconfigure
+ enforce
+
+
+
+
+ org.springframework.boot:spring-boot-jackson
+ org.springframework.boot:spring-boot-jackson-test
+
+
+
+
+
+
+
+```
+
+> **封禁对象只有自动配置模块**,`tools.jackson` 系构件不在范围内——门禁守的是"`JsonMapper` Bean 不许出现",不是"Jackson 3 的类不许出现";把库一起禁掉会连带打死一批按「Jackson 3 在场」编写的第三方组件(见 §5.5⑧)。`spring-boot-jackson` / `spring-boot-jackson-test` 均为精确坐标匹配,**不会**误伤 `spring-boot-jackson2`。
+>
+> 该门禁 Boot 单体 / Cloud 微服务两个下游工程需各自挂一份——它们以 Boot BOM import 方式引用 blade-tool,并非以其为 parent,`` 不会继承过去。
+
+**⑧ 【必读】Jackson 3 的库本体必须留着(Cloud 侧尤其)**——⑥ 只剥自动配置模块,而 `tools.jackson` 的库是随该模块传递进来的,剥掉模块库也就跟着没了。若不补回来,凡是**编译期直接 `import tools.jackson.*`** 的第三方组件都会踩雷:轻则条件不命中静默降级,重则 `NoClassDefFoundError: tools/jackson/databind/ObjectMapper` 打断启动。Boot 单体不受影响(这些组件只存在于 Cloud 技术栈),Cloud 侧实测清单:
+
+| 组件 | 触发点 | 缺席后果 |
+|---|---|---|
+| `spring-cloud-circuitbreaker-sentinel` | `CircuitBreakerRuleChangeListener#afterSingletonsInstantiated` → `SentinelFeignClientProperties#copy()` 内 `new tools.jackson.databind.ObjectMapper()` | **容器 refresh 末尾抛错,服务起不来**;所有单例都建完了才炸,日志看着像启动成功 |
+| `spring-cloud-gateway-server-webflux` | `RemoveJsonAttributesResponseBodyGatewayFilterFactory` 的实例字段 `private ObjectMapper mapper = new ObjectMapper()`,该 Bean 由 `@ConditionalOnEnabledFilter` 默认开启 | **网关起不来** |
+| `spring-cloud-openfeign-core` | `PageJacksonModule` / `SortJacksonModule`,装配条件校验的模块基类在 Jackson 3 改名后退化为恒成立 | **容器启动失败**;见 `FeignJacksonEnvPostProcessor` 的兜底 |
+| `spring-boot-admin-client` | `RestClientRegistrationClientConfig#registrationClient` 形参 `ObjectProvider` | 配了 `spring.boot.admin.client.url` 才装配,装配即失败 |
+| `spring-cloud-alibaba-sentinel-datasource` | `JsonConverter` / `XmlConverter` | 静默不注册,Sentinel 规则数据源转换能力消失 |
+| `spring-cloud-starter-alibaba-sentinel` | `SentinelAutoConfiguration$SentinelConverterConfiguration` | 自带 `@ConditionalOnClass` 守卫,整块跳过,同上静默降级 |
+
+这些都不属于本工程可修的范围,逐个关开关是打地鼠——上表还只是**当前版本**的快照,三方库一升级又会冒出新的。所以口径是**留库**:
+
+- `blade-core-cloud` 引 `tools.jackson.core:jackson-databind`,覆盖全部微服务(经 `blade-core-boot` 传递)。
+- `blade-gateway` 不含 `blade-core-cloud`,需在自己的 POM 里单独引一份,否则会被上表第二行打挂。
+- 版本由 Boot BOM 托管(`spring-boot-dependencies` 已 import `tools.jackson:jackson-bom`),不必自设版本属性。
+
+留库**不会**翻转管线:§5.5⑤ 已实测 Jackson 3 转换器分支要的是 `@ConditionalOnBean(JsonMapper)`,而该 Bean 只由被剥离的 `spring-boot-jackson` 产出。`FeignJacksonEnvPostProcessor` 也据此加了 `ClassUtils.isPresent("tools.jackson.databind.JacksonModule")` 守卫——Jackson 3 在场就不干预,交回上游条件判定,只在缺席时才给出关闭默认值。
+
+> 排查手法(升级三方库后建议复跑):对依赖树里的 jar 逐个扫常量池,`tools/jackson` 命中即为硬引用嫌疑,再回源码看有没有条件守卫。用 Python 的 `zipfile` 扫,别用 `strings`——macOS 的 `strings` 会把 `.class` 的 `0xCAFEBABE` magic 误判成 Mach-O fat 二进制,扫出空结果。
+
### 5.6 Redis pub/sub 容器与 Boot 4.1 新增 `@RedisListener` 自动配置的竞争
**背景**:Boot 4.1 的 `spring-boot-data-redis` 新增了注解驱动监听自动配置 `DataRedisAnnotationDrivenConfiguration`(由 `DataRedisAutoConfiguration` `@Import`,条件 `@ConditionalOnClass({org.springframework.data.redis.annotation.EnableRedisListeners, org.springframework.messaging.Message})`),用于支撑新的 `@RedisListener` 注解。它会注册一个 `@Bean(name = "redisMessageListenerContainer")` + `@ConditionalOnMissingBean` 的默认容器。
diff --git a/pom.xml b/pom.xml
index 8a4bf1f..ff4a29b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,7 +36,7 @@
- 5.0.0
+ 5.0.1
org.springblade.blade.tool
21
@@ -60,6 +60,7 @@
1.2.28
2.0.13
4.5.14
+ 3.6.3
4.1.0
4.1.1
@@ -127,6 +128,23 @@
${mica.auto.version}
provided
+
+
+ org.springframework.boot
+ spring-boot-starter-jackson
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-jackson
+
+
+
org.springblade
@@ -380,15 +398,28 @@
swagger-annotations-jakarta
2.2.52
+
org.springdoc
springdoc-openapi-starter-webflux-ui
3.0.3
+
+
+ org.springframework.boot
+ spring-boot-jackson
+
+
org.springdoc
springdoc-openapi-starter-webmvc-ui
3.0.3
+
+
+ org.springframework.boot
+ spring-boot-jackson
+
+
@@ -420,6 +451,12 @@
easy-captcha
1.6.2
+
+
+ com.alibaba
+ fastjson
+ 2.0.64
+
cn.idev.excel
@@ -532,6 +569,42 @@
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ ${maven.enforcer.version}
+
+
+ ban-jackson3-autoconfigure
+
+ enforce
+
+
+
+
+
+ org.springframework.boot:spring-boot-jackson
+ org.springframework.boot:spring-boot-jackson-test
+
+
+ 检测到 spring-boot-jackson 进入依赖树。该模块会注册 JsonMapper Bean,
+ 使 Boot 4 改用 Jackson 3 的消息转换器,
+ @BladeView 视图过滤、大数转字符串、日期格式等序列化约定将静默失效。
+ 请执行 mvn dependency:tree -Dincludes='org.springframework.boot:spring-boot-jackson'
+ 定位引入路径,并在父 POM dependencyManagement 对应条目补充排除。
+ 注意:tools.jackson 系构件本身不在封禁范围,可以正常引入。
+
+
+
+
+
+
+
org.apache.maven.plugins
maven-compiler-plugin