在 Struts2 專案中使用 JSON 插件序列化 Hibernate 實體時,常遇到懶加載異常(LazyInitializationException)或代理類轉換異常(ClassCastException: ... cannot be cast to javassist.util.proxy.Proxy)。本文深度剖析兩類異常根因,提供黑名單過濾與Jar 包去重雙重解決方案。
Admin (1) → (N) Category (1) → (N) Product@ManyToOne(fetch = FetchType.LAZY)from Product p left join fetch p.category where p.name like :name在 struts.xml 中配置 excludeProperties 使用正則表達式排除懶加載屬性:
<package name="default" namespace="/" extends="json-default">
<action name="product*" class="com.action.ProductAction" method="{1}">
<result type="json">
<param name="excludeProperties">
category\.admin.* # 過濾 Category 下的 admin 屬性及其子屬性
</param>
<param name="includeProperties">
id,name,price,category\.id,category\.name # 顯式包含需要的屬性
</param>
</result>
</action>
</package>
json-default 包,使用 json 結果類型若配置黑名單後異常依然存在,檢查類路徑下 javassist 版本衝突:
javassist-3.11.0.GA.jarjavassist-3.x.x.GA.jar(版本可能不同)ClassCastExceptionmvn dependency:tree | grep javassistExternal Libraries 中是否存在多個 javassist jarpom.xml 中排除 struts2 帶入的 javassist<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.x</version>
<exclusions>
<exclusion>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
| 方案 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| 黑名單過濾 | 僅需控制 JSON 輸出字段,實體映射保持 LAZY | 非侵入式、靈活、不影響其他業務 | 若有多處序列化需維護多份配置 |
| 改為 EAGER | 關聯數據量小、必須同時加載 | 簡單直接 | 性能差、N+1 問題、違背領域模型設計 |
| Jar 包去重 | 出現 ClassCastException、代理類異常 | 根治底層衝突、修復所有潛在問題 | 需仔細排查依賴樹 |
excludeProperties 精準控制輸出mvn dependency:analyze 發現衝突OpenSessionInViewFilter 延長 Session 生命週期(需權衡事務邊界)Struts2 JSON 懶加載異常本質是序列化觸發未初始化代理。黑名單過濾是業務層面的精準手術刀;Jar 包衝突是技術層面的隱形殺手。兩者結合:先配黑名單解決業務,再查依賴鞏固基石,才能徹底擺脫「序列化噩夢」。