Struts 2 參數傳遞核心建立在 OGNL(Object-Graph Navigation Language)與 ValueStack(值棧)之上。框架主要完成兩項工作:
Action 擁有 User user 屬性及 getter/setter,表單欄位命名為 user.name、user.age 即可自動填充。
XWork 2.1+ 內建支援。若使用舊版,需在 classpath 下放置 xwork-conversion.properties:
java.lang.Enum=com.opensymphony.xwork2.util.EnumTypeConverter
範例:
public enum Gender { MALE, FEMALE }
public class User { private Gender gender; /* getter/setter */ }
<select name="user.gender">
<option value="MALE">男</option>
<option value="FEMALE">女</option>
</select>
XWork 預設支援多種日期格式,但實務上常需自訂格式(如 yyyy-MM-dd)。建議實作自訂 DateConverter 並註冊為全域轉換器。
<input name="users[0].name" value="aaa"/>
<input name="users[1].name" value="bbb"/>
// 方式一:泛型(推薦,無需額外配置)
private List<User> users;
// 方式二:@Element 註解(無泛型時)
@Element(value = User.class) private List users2;
<input name="userMap['user1'].name" value="eee"/>
<input name="userMap['user2'].name" value="fff"/>
// 泛型
private Map<String, User> userMap;
// 註解:value 對應 Map 的 value 類型
@Element(value = User.class) private Map userMap2;
由 FileUploadInterceptor 處理,必須在 params 攔截器之前:
<interceptor-stack name="uploadStack">
<interceptor-ref name="upload"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
Action 中聲明:
private File upload;
private String uploadFileName; // 自動注入原始檔名
private String uploadContentType; // 自動注入 MIME 類型
注意:框架提供的是臨時文件,Action 結束後自動刪除,必須在 Action 中自行持久化(複製到目標目錄或存入資料庫)。
public class FileComponent implements Serializable {
private File upload;
private String fileName;
// getter/setter...
public void setUploadFileName(String uploadFileName) { this.fileName = uploadFileName; } // 關鍵:攔截器尋找 setXxxFileName
}
Action 使用 FileComponent[] uploads 即可統一管理多文件上傳。
實作 TypeConverter 介面,註冊於 OGNL 上下文:
public class DateConverter extends DefaultTypeConverter {
private static final String[] PATTERNS = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM"};
@Override public Object convertValue(Map context, Object value, Class toType) {
if (toType == Date.class) return convertToDate(value);
if (toType == String.class) return convertToString(value);
return super.convertValue(context, value, toType);
}
private Date convertToDate(Object value) {
if (value instanceof String) {
Date d = DateUtils.parseDate((String)value, PATTERNS);
if (d == null) try { return new Date(Long.parseLong((String)value)); } catch (Exception ignored) {}
} else if (value instanceof Object[]) { return convertToDate(((Object[])value)[0]); }
else if (value instanceof Date) return (Date)value;
return null;
}
private String convertToString(Object value) {
return value instanceof Date ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date)value) : null;
}
}
註冊方式(xwork-conversion.properties):
java.util.Date=com.example.converter.DateConverter
或類級別註冊(ActionName-conversion.properties):
dateField=com.example.converter.OtherDateConverter
Struts 2 透過 OGNL + 攔截器鏈提供極具彈性的參數綁定機制。掌握 泛型優於註解、全域轉換器優於類級別、臨時文件必須手動持久化 等最佳實踐,能避開常見坑點,編寫健壯的表單處理邏輯。