【发布时间】:2016-05-29 04:09:40
【问题描述】:
以下是一个转换器,主要用于修剪前导和尾随空格,并用单个空格替换句子或文本中单词之间的多个空格。转换器现已修改为将null 或空字符串替换为“不可用”(如果需要,可以动态本地化)。
@FacesConverter(forClass = String.class)
public class StringTrimmer implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return Boolean.TRUE.equals(component.getAttributes().get("skipConverter")) ? value : value == null ? null : value.trim().replaceAll("\\s+", " ");
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return Boolean.TRUE.equals(component.getAttributes().get("skipConverter")) ? value == null ? null : value.toString() : value == null || ((String) value).trim().length() == 0 ? "Not available" : ((String) value).trim().replaceAll("\\s+", " ");
}
}
由于未调用转换器,当模型值为 null 基于 the previous question 时,com.sun.faces.renderkit.html_basic.TextRenderer 已扩展以调用转换器,当关联模型中的属性值为 null。
public final class HtmlBasicRenderer extends TextRenderer {
@Override
public String getCurrentValue(FacesContext context, UIComponent component) {
if (component instanceof UIInput) {
Object submittedValue = ((UIInput) component).getSubmittedValue();
if (submittedValue != null) {
return submittedValue.toString();
}
}
return getFormattedValue(context, component, getValue(component));
}
}
following 条件测试已被移除,因此即使遇到null 值,也可以调用getFormattedValue() 方法。
Object currentObj = getValue(component);
if (currentObj != null) {
currentValue = getFormattedValue(context, component, currentObj);
}
这个已经在faces-config.xml注册了,如下。
<render-kit>
<renderer>
<component-family>javax.faces.Output</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>com.example.renderer.HtmlBasicRenderer</renderer-class>
</renderer>
</render-kit>
当目标模型中的属性值返回 null 时,转换器 StringTrimmer 仍未被调用 (getAsString())。
在整个应用程序的任何地方都像#{empty bean.value ? 'Not available' : bean.value} 这样在EL 中进行条件测试是很疯狂的。有什么建议吗?
这是 Mojarra 2.2.12。
更新:
转换值可用,当getFormattedValue() 方法中的一个返回语句返回一个空字符串"",当currentValue 是null,被修改为在调用中返回一个转换后的值
javax.faces.convert.Converter.getAsString(FacesContext context, UIComponent component, Object value)
在那个方法getFormattedValue().
因此,following,
if(currentValue == null) {
return "";
}
需要替换为,
if (currentValue == null) {
converter = Util.getConverterForClass("".getClass(), context);
return converter == null ? "" : converter.getAsString(context, component, currentValue);
}
(需要建议)。
【问题讨论】:
-
您在哪个组件中尝试此操作(因为您将其创建为通用
forClass =String.class)如果只是在 outputText 中,我会使用 simpleCustom 组件并搜索/替换默认的 jsf 或 primeFaces有了这个。 -
基本上是
<h:outputText>。可以为选定的可选字段创建自定义组件,但需要仔细记住哪些字段可能包含空值或空值。 -
好吧,你隐含地声明(通过使用'forClass = String.class')它适用于每个字符串?因此,无需记住事情。始终使用自定义
<tiny:outputText>;-) -
到处使用自定义组件?我将
<h:outputText>组件与<my:convertBigDecimal percent="true" groupingUsed="true" locale="#{localeBean.locale}"/>、<my:convertBigDecimal currency="#{currencyRateBean.currency}" groupingUsed="true" locale="#{localeBean.locale}"/>之类的转换器一起使用。因此,它需要根据目标<h:outputText>组件所指的模型值类型来创建不同的自定义组件。