2013年2月4日 星期一

Struts2 Type Conversion

在Struts1使用Commons BeanUtils做為type conversion的工具,在Struts2則改用OGNL,細節可參考:Type Conversion

不管用哪種技術,它們的目的都是為了在model中直接宣告資料正確的型別,然後透過type conversion在data binding時直接處理資料的型別轉換,如果型別轉換失敗,錯誤訊息會透過ConversionErrorInterceptor塞入field error裡面,不過程式開發的原則應該是盡量避開conversion error的產生才對。

以下我們自訂一個PercentFormatConverter,專門處理具有%符號的數字轉換。
NumberFormatConverter
package com.gss.gmo.cao.struts2.conversion;

import static java.text.NumberFormat.getNumberInstance;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.commons.lang3.ArrayUtils.isEmpty;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Map;

import org.apache.struts2.util.StrutsTypeConverter;

public class NumberFormatConverter extends StrutsTypeConverter {

    private NumberFormat numberFormat = getNumberInstance();

    public void setNumberFormat(NumberFormat numberFormat) {
        this.numberFormat = numberFormat;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
        if (isEmpty(values)) {
            return null;
        }

        if (!toClass.isArray() && values.length == 1) {
            return convertFromString(context, values[0], toClass);
        }

        String[] numbers = new String[values.length];
        for (int i = 0; i < values.length; i++) {
            try {
                numbers[i] = numberFormat.parse(values[i]).toString();
            } catch (ParseException e) {
                numbers[i] = null;
            }
        }
        return performFallbackConversion(context, numbers, toClass);

    }

    @SuppressWarnings("rawtypes")
    private Object convertFromString(Map context, String value, Class toClass) {
        if (isBlank(value)) {
            return null;
        }

        String number;
        try {
            number = numberFormat.parse(value).toString();
        } catch (ParseException e) {
            number = null;
        }
        return performFallbackConversion(context, number, toClass);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public String convertToString(Map context, Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof String) {
            return (String) object;
        }

        return numberFormat.format(object);
    }

}
PercentFormatConverter
package com.gss.gmo.cao.struts2.conversion;

import static java.text.NumberFormat.getPercentInstance;

public class PercentFormatConverter extends NumberFormatConverter {

    public PercentFormatConverter() {
        setNumberFormat(getPercentInstance());
    }

}
設定方式就詳閱官方文件,這裡不多做贅述。