使用@FacesConverter覆盖JSF转换器javax.faces.convert.BigDecimalConverter,转而使用自定义转换器(forClass = BigDecimal.class)

时间:2015-07-29 02:37:01

标签: jsf converter bigdecimal

我有以下通用BigDecimal转换器(深入检查代码绝对是多余的)。

@FacesConverter(value = "bigDecimalConverter")
public class BigDecimalConverter implements Converter {

    @Inject
    private CurrencyRateBean currencyRateBean; // Maintains a currency selected by a user in his/her session.

    private static final int scale = 2; // Taken from an enum.

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (!StringUtils.isNotBlank(value)) {
            return null;
        }

        try {
            BigDecimal bigDecimal = new BigDecimal(value);
            return bigDecimal.scale() > scale ? bigDecimal.setScale(scale, RoundingMode.HALF_UP).stripTrailingZeros() : bigDecimal.stripTrailingZeros();
        } catch (NumberFormatException e) {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Message"), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null) {
            return "";
        }

        BigDecimal newValue;
        if (value instanceof Long) {
            newValue = BigDecimal.valueOf((Long) value);
        } else if (value instanceof Double) {
            newValue = BigDecimal.valueOf((Double) value);
        } else if (!(value instanceof BigDecimal)) {
            throw new ConverterException("Message");
        } else {
            newValue = (BigDecimal) value;
        }

        final String variant = (String) component.getAttributes().get("variant");

        if (variant != null) {
            if (variant.equalsIgnoreCase("grouping")) {
                DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance();
                formatter.setGroupingUsed(true);
                formatter.setMinimumFractionDigits(scale);
                formatter.setMaximumFractionDigits(scale);
                return formatter.format(newValue);

            } else if (variant.equalsIgnoreCase("currency")) {
                String currency = currencyRateBean.getCurrency();
                DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(new Locale("en", new String(currency.substring(0, 2))));
                formatter.setDecimalFormatSymbols(formatter.getDecimalFormatSymbols());
                formatter.setCurrency(Currency.getInstance(currency));
                return formatter.format(newValue);
            }
        }

        DecimalFormat formatter = (DecimalFormat) NumberFormat.getNumberInstance();
        formatter.setGroupingUsed(false); // Not necessary.
        formatter.setMinimumFractionDigits(scale);
        formatter.setMaximumFractionDigits(scale);
        return formatter.format(newValue);
    }
}

这可以使用如下。

<h:outputText value="#{bean.value}">
    <f:converter converterId="bigDecimalConverter"/>
    <f:attribute name="variant" value="grouping"/>
</h:outputText>

根据variant<f:attribute>的值,它会将值转换为等值货币($ 123)或使用组(11,111)的值。其他标准也可以定义为并且在需要时,即不需要用于其他类型格式的单独转换器(如果有的话)。转换器的默认任务是将值向上舍入为两个小数点。

为了避免提及,

<f:converter converterId="bigDecimalConverter"/>

converter="#{bigDecimalConverter}"无处不在,转换器类需要用

进行修饰
@FacesConverter(forClass = BigDecimal.class)

这样做,JSF事先采用了自己的javax.faces.convert.BigDecimalConverter。我试过扩展那个课程,但没有任何区别。

是否可以覆盖默认的JSF javax.faces.convert.BigDecimalConverter,以便通过指定forClass = BigDecimal.class来使用我们自己的转换器,这样就不需要使用<f:converter converterId="bigDecimalConverter"/>或{{1在任何地方?

2 个答案:

答案 0 :(得分:3)

通常,覆盖默认转换器(以及验证器,组件和渲染器)不能在相同的标识符上进行注释。它必须在webapp自己的faces-config.xml中明确注册。

如果您打算覆盖converter="javax.faces.BigDecimal",请执行以下操作:

<converter>
    <converter-id>javax.faces.BigDecimal</converter-id>
    <converter-class>com.example.YourBigDecimalConverter</converter-class>
</converter>

如果您打算覆盖类型java.math.BigDecimal的隐式转换,请执行以下操作:

<converter>
    <converter-for-class>java.math.BigDecimal</converter-for-class>
    <converter-class>com.example.YourBigDecimalConverter</converter-class>
</converter>

你需要后者。

答案 1 :(得分:1)

更换默认转换器应遵循以下步骤:

  1. 扩展您计划替换的默认转换器,以避免类转换异常。在您的情况下,这将是javax.faces.convert.BigDecimalConverter

  2. faces-config.xml 中注册转换器,指定与默认值对应的<converter-id>。这允许您覆盖默认值。你将要做的是:

         <converter>
             <converter-class> 
                  com.you.YourBigDecimalConverter
             </converter-class> 
             <converter-id>
                  javax.faces.BigDecimal
             </converter-id>
        </converter>