开源社区遵循了一套约定叫语义化版本(SemVer):版本号 MAJOR.MINOR.PATCH,比如 2.15.2。
| 段 | 变化时 | 你的代码会怎样 |
|---|---|---|
MAJOR(1.0.0 → 2.0.0) | 不兼容 API 变更 | 旧代码可能跑不起来 |
MINOR(2.14.0 → 2.15.0) | 加新功能,向后兼容 | 旧代码照跑 |
PATCH(2.15.1 → 2.15.2) | 修 bug,向后兼容 | 放心升级 |
看到 MAJOR 变化就要读 changelog。
版本范围符号
json
{
"lodash": "^4.17.21", // 4.x.x 内随便升级
"express": "~4.18.2", // 4.18.x 内升级
"debug": "4.3.4" // 锁死
}| 写法 | 含义 | 实际范围 |
|---|---|---|
^2.15.2 | 主版本内随便升 | >=2.15.2 <3.0.0 |
~2.15.2 | 次版本内随便升 | >=2.15.2 <2.16.0 |
2.15.2 | 锁定 | 只装 2.15.2 |
传递依赖与冲突
一个库依赖别的库——比如 Jackson → jackson-core。包管理器自动处理这个链条。
但如果两个依赖要不同版本的同个库?Lib A 要 jackson-core 2.14,Lib B 要 2.15——这就是依赖冲突。
不同工具的策略:
- Maven:"最近优先"
- Gradle:选最高版本
- npm/pip:各自装独立副本(可共存)
用 dependency:tree 排查
bash
mvn dependency:tree输出示例:
+- jackson-databind:jar:2.15.2:compile
| \- jackson-core:jar:2.15.2:compile
\- lib-b:jar:1.0:compile
\- jackson-core:jar:2.14.0:compilejackson-core 出现两个版本。Maven 选 2.15.2(路径更短)。万一出事,用 <exclusions>:
xml
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-b</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>快速自查
| 场景 | 动作 |
|---|---|
| 依赖更新后项目崩了 | 检查 MAJOR 版更;读 changelog |
| 两个库要不同版本的同一依赖 | mvn dependency:tree |
| 想彻底锁死版本 | 写死版本号 |
| 装了库但没生效 | 看是不是被冲突策略排除了 |
→ 下一章
动手练习 + 排障走一遍。