全面解析 Struts 2 類型轉換機制:從自定義轉換器繼承體系、OGNL 表達式隱式轉換、集合泛型支援、內建轉換器清單,到錯誤處理攔截器與國際化訊息定制。
DefaultTypeConverter實作 convertValue(Map context, Object value, Class toType),雙向邏輯寫在同一方法。value 為字串陣列(request.getParameterValues())。
StrutsTypeConverter(推薦)抽象子類別,實作兩個方法:
convertFromString(Map context, String[] values, Class toClass):請求 → 物件convertToString(Map context, Object o):物件 → 字串關鍵點:convertFromString 第二參數為字串陣列,可處理請求陣列(如 ?u=1&u=2&u=3),Action 對應屬性為陣列或 List。返回類型依 toClass 判斷(陣列或 List)。
Action 有屬性 User user,JSP 輸入框命名 user.name、user.pass:
<s:textfield name="user.name" label="用戶名"/>
<s:textfield name="user.pass" label="密碼"/>
提交後 Struts 2 自動:new User() → setName()/setPass() → setUser(user)。三個必要條件:
setUser()(getUser() 亦需)<s:textfield name="users['one'].name" label="第一個用戶名"/>
<s:textfield name="users['one'].pass" label="第一個密碼"/>
<s:textfield name="users['two'].name" label="第二個用戶名"/>
<s:textfield name="users['two'].pass" label="第二個密碼"/>
<s:textfield name="users[0].name" label="第一個用戶名"/>
<s:textfield name="users[0].pass" label="第一個密碼"/>
<s:textfield name="users[1].name" label="第二個用戶名"/>
<s:textfield name="users[1].pass" label="第二個密碼"/>
get 機制與邊界情況getXxx():null 則構造新實例(Map/List/User);已有實例則保留其他屬性值users[1])會導致 users[0]=nullUser[](陣列不支援動態擴展)無泛型時 Action 僅宣告 Map users 或 List users,需在 ActionName-conversion.properties 指定:
# List 元素類型
Element_users=com.unmi.vo.User
# Map Key/Value 類型
Key_users=java.lang.String
Element_users=com.unmi.vo.User
Struts 2 要求 JDK 1.5+ 主因即泛型免配置。JDK 1.4 需大量 conversion 檔案。
Set 無序無索引,需指定索引屬性:
Element_users=com.unmi.vo.User
KeyProperty_users=name <!-- User 的 name 屬性作為索引 -->
提交頁面用圓括號:users('scott').name。顯示同樣用圓括號。一般建議用 List 替代 Set。
boolean/Boolean、char/Character、int/Integer、long/Long、float/Float、double/DoubleDate:請求 Locale 的 SHORT 格式XWorkList(String.class, Object[]));泛型如 List<Integer> → XWorkList(Integer.class, Object[]),XWorkList 繼承 ArrayList預設攔截器棧含 conversionError 攔截器,自動封裝為 fieldError 放入 ActionContext。開發者只需:
ActionSupportstruts.xml 宣告 <result name="input"><s:textfield> 等標籤(錯誤自動顯示在輸入框上方)xwork.default.invalid.fieldvalue={0}欄位類型轉換失敗!ActionName.properties 加 invalid.fieldvalue.屬性名=提示訊息(如 invalid.fieldvalue.number=數量格式錯誤)同名輸入框多個出錯:手工 <s:fielderror/> 僅顯示一條;用標籤 <s:textfield> 則每個出錯框皆顯示。