JSON 依賴坑點實錄:從手動導 Jar 到 Maven 坐標的正確姿勢
使用 `net.sf.json.JSONObject` 時遇到 `java.lang.NoClassDefFoundError: net/sf/json/JSONObject`,折騰半天最終發現是依賴管理不規範導致。記錄排查過程與標準解法。
錯誤重現與錯誤嘗試
- 現象:編譯通過,運行拋 `NoClassDefFoundError`。
- 嘗試 1:Project Properties → Java Build Path → Libraries → Add External JARs 選中 `json-lib-2.3-jdk15.jar`。無效,運行時類加載器找不到。
- 嘗試 2:將 Jar 複製到 `TOMCAT_HOME/lib/`。報新錯:`org.apache.commons.lang.exception.NestableRuntimeException` (缺少傳遞依賴 commons-lang)。
根因分析
- 手動導 Jar 只解決編譯期類路徑,運行時類加載器 (WebAppClassLoader) 不會掃描 Build Path 添加的外部 Jar,除非放在 `WEB-INF/lib/`。
- 放入 Tomcat 共享 lib 污染全局類加載器,且缺少傳遞依賴 (`commons-lang`, `commons-beanutils`, `commons-collections`, `commons-logging`, `ezmorph`)。
- 本質:項目原為 Maven 管理,新項目 `pom.xml` 缺失該依賴坐標。
標準解決方案:Maven 坐標一鍵搞定
在 `pom.xml` `` 中添加:
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.3</version>
<classifier>jdk15</classifier> <!-- 關鍵:指定 JDK 版本分類器 -->
</dependency>
關鍵點說明
classifier:`json-lib` 同版本提供多個 JDK 編譯版本 (jdk13, jdk15, jdk16, jdk17),必須指定與項目 JDK 匹配的分類器,否則 Maven 會下載無分類器的主 Jar (可能不包含類文件)。
- 傳遞依賴自動解決:Maven 會自動下載 `commons-lang`, `ezmorph` 等所需依賴並打包進 `WEB-INF/lib/`,零手動干預。
- 作用域:默認 `compile`,打包 WAR 時自動進入 `WEB-INF/lib/`,運行期類加載器可見。
避坑清單
- ✅ 統一使用 Maven 管理依賴,拒絕手動導 Jar / 複製到容器 lib。
- ✅ 多模塊項目在父工程 `` 鎖定版本,子模塊引用無需寫版本。
- ✅ 遇到 `NoClassDefFoundError` 優先檢查:`mvn dependency:tree` 確認依賴是否到達、`mvn clean package` 確認 `WEB-INF/lib` 是否存在 Jar。
- ✅ 新項目從舊項目複製 `pom.xml` 依賴片段時,務必同步 `` 和 `` 版本定義。