Mall4j 这个开源电商系统沉寂了一段时间后,直接跳到了 4.0 大版本——不是小修小补,而是把核心依赖全线拉升:Spring Boot 从 3.x 到 4.x,MyBatis-Plus、Redisson、微信 Java SDK、SpringDoc 各自升到新版本,同时把 fastjson 和 spring-cloud-commons 两块"旧包袱"彻底砍掉。对于已经在 Mall4j 3.x 上跑项目的团队,这次升级不是改个版本号就能完事的,下面逐项拆解改动背后的影响和实操要点。
依赖升级:版本号背后的兼容性暗坑
先看升级清单和每个变更的实际影响面:
| 依赖 | 旧版本区间 | 新版本 | 升级影响 |
|---|---|---|---|
| Spring Boot | 3.x | 4.x | 配置属性、自动装配机制、Servlet 容器适配可能变动 |
| MyBatis-Plus | 旧版 | 3.5.16 | 分页插件、Lambda 查询 Wrapper API 有微调 |
| Redisson | 旧版 | 4.3.0 | 配置格式、分布式锁 API 有变更 |
| WeiXinJava | 旧版 | 4.8.0 | 微信支付 V3 接口适配更完整,旧 API 可能标记 deprecated |
| SpringDoc | 旧版 | 3.0.2 | 与 Spring Boot 4 的 OpenAPI 自动扫描规则对齐 |
Spring Boot 4.x 是最重的一刀。如果之前项目里用了 spring-boot-properties-migrator 做兼容过渡,4.x 里部分已废弃的属性会被直接移除。比如 spring.redis.* 系列配置在 3.x 已经迁移到 spring.data.redis.*,4.x 阶段旧 key 不再兼容。Redisson 4.x 的配置也要求对应调整。
MyBatis-Plus 3.5.16 的分页插件在多数据源场景下对 DbType 的自动推断逻辑做了修正,如果你的 Mall4j 项目用了多租户或多数据源,跑完升级后务必验证分页 SQL 是否仍然正确。
移除 fastjson:安全债终于清了
fastjson 被移除是这次升级里最值得叫好的决定。fastjson 的反序列化漏洞历史长到可以单独写篇文章,从任意代码执行到绕补丁再绕补丁,修不完。Mall4j 4.0 把它砍掉,意味着项目里所有 JSON 序列化/反序列化统一走 Jackson(Spring Boot 默认自带)。
但移除不等于删一行依赖就完事。如果你的业务代码里有直接 JSONObject.parseObject() 或 JSON.toJSONString() 的调用,必须全部替换。下面是典型的替换对照和可直接用的代码片段:
// === 旧代码(fastjson) ===
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
// 反序列化
UserDTO user = JSON.parseObject(jsonStr, UserDTO.class);
// 序列化
String jsonStr = JSON.toJSONString(user);
// 取嵌套字段
String name = JSONObject.parseObject(jsonStr).getString("name");
// === 新代码(Jackson) ===
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
ObjectMapper mapper = new ObjectMapper();
// 反序列化
UserDTO user = mapper.readValue(jsonStr, UserDTO.class);
// 序列化
String jsonStr = mapper.writeValueAsString(user);
// 取嵌套字段(用 JsonNode 替代 JSONObject 的灵活取值)
import com.fasterxml.jackson.databind.JsonNode;
JsonNode root = mapper.readTree(jsonStr);
String name = root.path("name").asText();
迁移前必做的事:全局搜索 com.alibaba.fastjson 的 import,逐个替换。注意 fastjson 默认忽略空字段,而 Jackson 默认输出 null——如果你的 API 对外契约要求空字段不输出,在 Jackson 里加配置:
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
或者直接在 application.yml 里全局控制:
spring:
jackson:
default-property-inclusion: non_null
serialization:
write-dates-as-timestamps: false
移除 spring-cloud-commons:轻量化路线
spring-cloud-commons 提供的是服务发现、负载均衡等微服务基础设施抽象。Mall4j 把它移除,说明 4.x 版本在架构倾向上更偏向单体或轻量部署,不再强制绑定 Spring Cloud 全套。
如果你的部署方式本来就是单实例或 Nginx 前端负载均衡,移除没有影响。但如果你之前用了 @LoadBalanced 注解给 RestTemplate 或 WebClient 做服务间调用,升级后这段代码会编译报错。替代方案:
- 用 Nginx 或网关层做路由转发,服务间直接写目标地址。
- 如果仍需要客户端负载均衡,单独引入
spring-cloud-starter-loadbalancer(不依赖完整 spring-cloud-commons),或切换到 Resilience4j 做重试和熔断。
# 示例:只引入 loadbalancer,不拉整套 spring-cloud
# pom.xml 中单独添加
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>4.0.0</version>
</dependency>
升级实操 Checklist
把上面拆解的内容收拢成一份可执行的迁移清单:
- POM 依赖替换:把 Spring Boot parent 版号改到 4.x 对应版本,MyBatis-Plus、Redisson、WeiXinJava、SpringDoc 版本号同步更新,删除 fastjson 和 spring-cloud-commons 依赖声明。
- 配置文件扫描:检查
application.yml/application.properties里所有spring.redis.*、spring.mvc.*等可能被重命名的 key,对照 Spring Boot 4.x 迁移指南逐条修正。 - fastjson 代码全局替换:搜索所有 fastjson 引用,按上面的 Jackson 替换模式逐个改写,补充空字段策略配置。
- Redisson 配置对齐:Redisson 4.x 的
redisson.yaml或 Spring 配置格式有调整,检查锁、队列、缓存相关 Bean 的初始化代码。 - 微信支付接口验证:WeiXinJava 4.8.0 对 V3 接口支持更完善,但旧版 V2 接口的调用方式可能标记 deprecated,跑一遍支付流程确认不报错。
- API 文档验证:SpringDoc 3.0.2 配合 Spring Boot 4.x 的自动扫描规则有变化,启动后访问
/swagger-ui.html或/v3/api-docs确认接口列表完整。 - 分页与多数据源回归测试:MyBatis-Plus 分页插件升级后,跑核心业务列表页的 SQL 日志,确认分页参数和总数统计正确。
升级大版本最怕的不是显式报错,而是隐式行为变化——分页偏移、序列化差异、配置 key 静默失效。按这份清单逐项验证,比直接上线后排查省几倍时间。