自動型変換とは
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クラスごとに設定する例は?
長くなるので分けます(´・ω・`)