众所周知,我们可以轻松编写自定义对流器并将其注册到组件,如下所示:
<f:converter converterId="cId" />
或
<f:converter binding="#{mybean}" />
对我们的需求进行了研究。但现在考虑UIInput
的源代码,它们负责确切的转换(评论已被忽略):
protected Object getConvertedValue(FacesContext context,
Object newSubmittedValue) throws ConverterException {
Renderer renderer = getRenderer(context);
Object newValue;
if (renderer != null) {
newValue = renderer.getConvertedValue(context, this,
newSubmittedValue); // <----------- 1
} else if (newSubmittedValue instanceof String) {
Converter converter = getConverterWithType(context);
if (converter != null) {
newValue = converter.getAsObject(context, this,
(String) newSubmittedValue);// <----------- 2
} else {
newValue = newSubmittedValue;
}
} else {
newValue = newSubmittedValue;
}
return newValue;
}
因此,很清楚我们选择了应该使用的转换器。此外,据我所知,如果某个组件具有单独的Renderer
,我们就无法应用在facelet中指定为标记的自定义转换器(因为if(renderer != null){...} else if(newSubmittedValue instanceof String){...}
)。例如<h:inputText />
组件类为UIInput
,并且它还有自定义com.sun.faces.renderkit.html_basic.TextRenderer
,因此getRenderer(context)
会返回不是null
的内容。因此,我们应该跳过converter
标记指定的转换,即使我们将其定义为
<h:inputText value="#{myBean.prop}"/>
<f:converter inding="#{bean}" />
</h:inputText>
inputText
有一个自定义渲染器,因此转换器不应该执行此处指定的任何操作:
Converter converter = getConverterWithType(context);
if (converter != null) {
newValue = converter.getAsObject(context, this,
(String) newSubmittedValue);// <----------- 2
} else {
newValue = newSubmittedValue;
}
你能解释一下吗?转换实际如何运作以及Renderer
转换器与我们的自定义converter
之间的差异是什么?
答案 0 :(得分:2)
实际上,渲染器也是如此。另请参见Renderer#getConvertedValue()
的javadoc。
尝试将以前存储的状态信息转换为此组件所需类型的对象(可选地使用此组件的已注册
Converter
(如果有的话))。如果转换成功,则应从此方法返回新值;如果没有,则应抛出ConverterException
。
如果Mojarra中有<h:inputText>
,则可以在HtmlBasicInputRenderer
中找到源代码。
此设计允许渲染器完全控制转换步骤,并在必要时操作此步骤。请注意,可以声明性地(通过faces-config.xml
)覆盖(标准)组件的渲染器,而无需在视图中更改组件本身。另请注意术语&#34;自定义渲染器&#34;在你的问题中并不完全正确。它只是标准的渲染器。我们谈论一个&#34;自定义渲染器&#34;只有当Web应用程序提供自己的应用程序时,才会覆盖标准的应用程序。