Web 應用基於 HTTP 協定,瀏覽器與伺服器交換的皆為字串。但伺服器端領域物件屬性類型多樣(Date、Integer、自訂類型等),需自動雙向轉換:字串 → 物件(表單提交)與 物件 → 字串(頁面顯示)。Struts 2 的 Converter 機制正是解決此問題。
package tutorial;
import java.util.Locale;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
public class HelloWorld extends ActionSupport {
private String msg;
private Locale loc = Locale.US;
public String getMsg() { return msg; }
public Locale getLoc() { return loc; }
public void setLoc(Locale loc) { this.loc = loc; }
@Override
public String execute() {
msg = LocalizedTextUtil.findDefaultText("HelloWorld", loc);
return SUCCESS;
}
}
<package name="ConverterDemo" extends="struts-default">
<action name="HelloWorld" class="tutorial.HelloWorld">
<result>/HelloWorld.jsp</result>
</action>
</package>
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:form action="HelloWorld" theme="simple">
Locale: <s:textfield name="loc" /> <s:submit />
</s:form>
<h2><s:property value="msg" /></h2>
package tutorial;
import java.util.Locale;
import java.util.Map;
import ognl.DefaultTypeConverter;
public class LocaleConverter extends DefaultTypeConverter {
@Override
public Object convertValue(Map context, Object value, Class toType) {
if (toType == Locale.class) {
String locale = ((String[]) value)[0];
return new Locale(locale.substring(0, 2), locale.substring(3));
} else if (toType == String.class) {
Locale locale = (Locale) value;
return locale.toString();
}
return null;
}
}
建立 xwork-conversion.properties 放在 classpath 根目錄:
java.util.Locale = tutorial.LocaleConverter
或針對特定 Action:建立 HelloWorld-conversion.properties 放在 Action 同包:
loc = tutorial.LocaleConverter
en_US → 顯示英文問候。zh_CN → 顯示中文問候。Struts 2 已內建常用類型轉換,無需自行實作:
int、boolean、double 等。DateFormat.SHORT)。Collection、Set、陣列,自動將 request.getParameterValues() 字串陣列轉換。單一表單提交多筆產品資料(名稱、價格、生產日期)。
Product:包含 name、price、dateOfProduction。ProductConfirm:屬性 List<Product> products。ProductConfirm-conversion.properties:
Element_products = tutorial.Product
指定 List 內部元素類型。<s:iterator value="new int[3]" status="stat">
<s:textfield name="%{'products['+#stat.index+'].name'}" />
<s:textfield name="%{'products['+#stat.index+'].price'}" />
<s:textfield name="%{'products['+#stat.index+'].dateOfProduction'}" />
</s:iterator>
products 列表。conversionError 攔截器(預設在 defaultStack)將轉換錯誤封裝為 FieldError,導向 input 結果。
<action name="ProductConfirm" class="tutorial.ProductConfirm">
<result>/ShowProducts.jsp</result>
<result name="input">/AddProducts.jsp</result>
</action>
<div style="color:red">
<s:fielderror />
</div>
price 預設 0.0)。Struts 2 轉換器機制: