自動型変換とは
Struts2には、画面からのリクエストパラメータに対し、自動的にString以外の型へ自動変換する仕組みがあります。これをTypeConvertionと呼びます。
デフォルトで自動型変換を行ってくれる型
自動型変換は、プリミティブ型、配列、java.util.ListなどがStruts2内部で実装済みです。
それ以外にも自動型変換したいけどできる?
Javaのクラスであればすべて可能です。手順は次の通りです。
- Struts2が提供するStrutsTypeConverterを継承したクラスを作る
- 型変換するよ!と宣言する
例えばBigDecimalをやってみよう
まず、TypeConverterクラスを継承して、BigDecimal用の型変換クラス、BigDecimalConvertoerを作ります。
継承して、以下の2メソッドを実装していきます。
public class BigDecimalConverter extends StrutsTypeConverter {
public Object convertFromString(
Map context,
String[] values,
Class toClass) {
// 画面→Actionクラス変換
}
public String convertToString(Map paramMap, Object paramObject) {
// 画面←Actionクラス変換(正常系のみ)
}
}
変換の設定はどこで?
Struts2では以下の2か所で設定できます。どちらかを選びましょう。
- 特定の型に対してすべて定義する : xwork-conversion.properties
- Actionクラスごとに定義する : [Actionクラス名]-conversion.properties
ちなみに、Actionクラスごとに定義する方法として、プロパティファイル以外にはアノテーションでも設定可能です。
次の例は、BigDecimal型はすべて変換する例です。
# BigDecimal
java.math.BigDecimal=lumi2.converter.BigDecimalConverter
型変換エラーを起こした時は?
作成したTypeConverterクラスのconvertFromStringメソッドにて、次のメソッドを呼ぶと、Struts2内部では「この項目は型変換が失敗したので表示用に元の値を表示する項目」になります。
super.performFallbackConversion(context, paramArrayOfString, toClass);
実装サンプル(BigDecimalConverter)
では実際の実装例です。複数同じ名前のパラメータがリクエストされても対応できるよう、配列チェックをしてから変換しています。
ついでに、カンマ編集をこのクラスで行っています。
public class BigDecimalConverter extends StrutsTypeConverter {
/**
* リクエストパラメータからの置換を行う。
* @param Map コンテキスト情報Map
* @param String[] パラメータの配列
* @param Class 変換後のクラス
* @return 型変換後のパラメータ(オブジェクト)
*/
@Override
public Object convertFromString(
Map context, String[] values, Class toClass) {
Object result = null;
log.debug("convertFromString -> " + context + ", "
+ values.toString() + ", " + toClass.getName());
if (values != null) {
if (values.getClass().isArray() && toClass.isArray()) {
Class<?> componentType = toClass.getComponentType();
result = Array.newInstance(componentType,
Array.getLength(values));
for (int i = 0, icount = Array.getLength(values); i < icount; i++) {
Array.set(result, i,
convertBigDecimalValue(
context ,
Array.get(values, i) ,
toClass
)
);
}
} else {
// カンマを取り除く
result = convertBigDecimalValue(context , values[0] , toClass);
}
}
return result;
}
/**
* BigDecimalへの型変換。
*
* @param Map コンテキスト情報Map
* @param Object 変換対象の文字列
* @param Class 変換後のクラス
* @return 型変換した後のオブジェクト
*/
protected Object convertBigDecimalValue(
Map context ,Object paramArrayOfString ,Class toClass
) {
BigDecimal result;
String value = (String)paramArrayOfString;
value = value.replace(",", "");
try {
// Struts2標準で持っているBigDecimal変換
result = bigDecValue(value);
} catch (NumberFormatException e) {
// 型変換エラーをStruts2へ通知する = JSPは変換前を表示
super.performFallbackConversion(context, paramArrayOfString, toClass);
return value;
}
return result;
}
/**
* BigDecimalからStringへの変換を行う。
* @param paramMap コンテキスト情報Map
* @param paramObject Actionクラスのフィールド
* @return 画面に表示する文字列
*/
public String convertToString(Map paramMap, Object paramObject) {
if ( paramObject instanceof BigDecimal ) {
NumberFormat fmt = NumberFormat.getInstance();
BigDecimal dec = new BigDecimal(paramObject.toString());
return fmt.format(dec);
} else {
return paramObject.toString();
}
}
}
アノテーションで設定する例、Actionクラスごとに設定する例は?
長くなるので分けます(´・ω・`)