使用 Apache POI 的 XWPFTemplate 動態合並生成 Word 文檔時,本地開發環境運行正常,但部署到 Linux 服務器(Tomcat)後拋出 NoSuchFieldError: RAW_XML_FILE_HEADER。經排查,根因是 Tomcat 共享類加載器目錄下存在多版本 POI JAR 包衝突。
java.lang.NoSuchFieldError: RAW_XML_FILE_HEADER
at org.apache.poi.xwpf.usermodel.XWPFDocument.<clinit>(XWPFDocument.java:...)
... 調用 XWPFTemplate.create(inputPath) 時觸發
| 環境 | POI JAR 版本 | 狀態 |
|---|---|---|
| 本地 IDEA (WEB-INF/lib) | poi-3.11-beta2, poi-ooxml-3.11-beta2 等統一版本 | ✅ 正常 |
| Linux Tomcat (共享 lib 目錄) | poi-3.13.jar, poi-3.15-beta2.jar 混雜存在 | ❌ 報錯 |

RAW_XML_FILE_HEADER 是 org.apache.poi.util.POILogFactory 或相關 OOXML 解析類中的常量字段。XWPFTemplate 內部調用 POI 核心類初始化時觸發 NoSuchFieldError。# 進入 Tomcat 共享 lib 目錄 cd $CATALINA_HOME/lib # 備份後刪除所有 poi* jar mv poi*.jar /tmp/poi-backup/ # 重新部署應用(應用自帶 WEB-INF/lib 下的正確版本)
重啟 Tomcat,應用類加載器將加載 WEB-INF/lib 下的統一版本,問題解決。
在 META-INF/context.xml 中設置:
<Context>
<Loader delegate="false" /> <!-- 先加載 WebApp 自身 lib,再委派父加載器 -->
</Context>
注意:可能導致 JSP 編譯、JDBC 驅動等依賴共享 lib 的資源找不到,需謹慎使用。
<dependencyManagement> 鎖定 POI 版本(如 5.2.3)。mvn dependency:tree 排查傳遞依賴引入的舊版本,用 <exclusion> 剔除。WEB-INF/lib 僅包含單一版本 POI 全套模塊。$CATALINA_HOME/lib 無任何 poi*、xmlbeans*、ooxml-schemas* 等業務 JAR。mvn dependency:analyze 檢測未聲明/未使用依賴。mvn enforce:enforce 禁止版本衝突。NoSuchFieldError、NoSuchMethodError、ClassNotFoundException 多數源於類加載器層級的 JAR 版本衝突。堅持「應用自帶依賴、共享 lib 極簡」原則,配合 Maven 強制版本管理,可從根源杜絕此類問題。