首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Struts 2 JSON 序列化父類屬性解決方案:ignoreHierarchy 參數詳解

     編輯:Java 程式設計入門

問題背景

專案使用 ExtJS 4 Grid 分頁,需回傳 totalCount、start、limit 三個分頁參數。為避免重複程式碼,建立基礎 BasePageAction 封裝分頁屬性,各業務 Action 繼承之。但 Struts 2 JSON 外掛預設 不序列化父類屬性,導致前端無法接收分頁資訊。

現象重現


// 父類
public class BasePageAction extends ActionSupport {
    private int totalCount;  // 總筆數
    private int start;       // 起始位置
    private int limit;       // 每頁筆數
    // getter/setter...
}

// 子類
public class UserAction extends BasePageAction {
    private List<User> userList;
    public String list() {
        userList = userService.findPage(start, limit);
        totalCount = userService.count();
        return "slist";
    }
}

// struts.xml
<package name="admin" namespace="/admin" extends="json-default">
    <action name="user_list" class="com.action.UserAction" method="list">
        <result name="slist" type="json" /> 
        <!-- 輸出缺少 totalCount, start, limit -->
    </action>
</package>

解決方案:配置 ignoreHierarchy=false


<action name="user_list" class="com.action.UserAction" method="list">
    <result name="slist" type="json">
        <param name="ignoreHierarchy">false</param>
    </result>
</action>

參數行為對照

ignoreHierarchy 值序列化範圍適用場景
true (預設)僅當前類別宣告的屬性 (含 getter)避免洩露父類內部狀態、安全敏感場景
false當前類別 + 所有父類屬性 (遞迴向上)基礎類封裝共用欄位 (分頁、通用回傳格式)

完整配置範例


<package name="api" namespace="/api" extends="json-default">
    <!-- 通用分頁結果配置 -->
    <action name="*_list" class="com.action.{1}Action" method="list">
        <result name="success" type="json">
            <param name="ignoreHierarchy">false</param>
            <param name="includeProperties">
                totalCount, start, limit, .*List\[\d+\]\..*
            </param>
        </result>
    </action>
</package>

搭配 includeProperties 精確控制輸出:父類分頁欄位 + 子類 List 明細欄位。

進階:基礎回傳封裝類模式


// 統一回傳格式
public class JsonResult<T> {
    private boolean success = true;
    private String message;
    private T data;
    private PageInfo page; // 分頁資訊物件
    // getter/setter...
}

// Action 直接回傳封裝物件
public class UserAction extends ActionSupport {
    private JsonResult<List<User>> result = new JsonResult<>();

    public String list() {
        result.setData(userService.findPage(...));
        result.setPage(new PageInfo(total, start, limit));
        return SUCCESS;
    }
}

// struts.xml 僅需 root=result
<result type="json">
    <param name="root">result</param>
</result>

此模式不需 ignoreHierarchy,因所有資料封裝在單一物件中,結構更清晰、擴充性更強。

常見問題排查

  1. 雙向關聯導致循環引用:父子物件互相引用 → StackOverflowError
    • 解決:excludeProperties=".*\\.parent, .*\\.children" 或實體加 @JsonIgnore
  2. 父類私有欄位無 getter:JSON 外掛只序列化 getter 方法
    • 解決:父類欄位必須有 public getter
  3. 多層繼承效能:深層繼承鏈 + ignoreHierarchy=false 會遍歷所有祖先
    • 建議:繼承層級 ≤ 3、或改用組合模式

JSON 外掛版本相容性

Struts 2 版本JSON PluginignoreHierarchy 支援
2.3.xstruts2-json-plugin✅ 支援
2.5.xstruts2-json-plugin✅ 支援
6.xstruts2-json-plugin (Jakarta EE)✅ 支援

總結

ignoreHierarchy=false 是解決 Struts 2 JSON 序列化父類屬性的標準開關。但更推薦使用組合模式 (JsonResult 封裝類) 替代繼承,避免繼承耦合、循環引用、效能隱患。若必須用繼承,請務必搭配 includeProperties/excludeProperties 精確控制輸出範圍,確保 API 穩定、安全、高效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved