当组件具有渲染器时似乎不使用转换器
Converter does not seem to be used when component has a renderer
众所周知,我们可以轻松编写自定义转换器并将其注册到组件中,如下所示:
<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 />
组件 class 是 UIInput
,它还有一个自定义的 com.sun.faces.renderkit.html_basic.TextRenderer
,因此 getRenderer(context)
returns 不是 [=22] =].因此,我们应该跳过 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
之间有什么区别
实际上,渲染器也是这样做的。另请参阅 Renderer#getConvertedValue()
.
的 javadoc
Attempt to convert previously stored state information into an object of the type required for this component (optionally using the registered Converter
for this component, if there is one). If conversion is successful, the new value should be returned from this method; if not, a ConverterException
should be thrown.
对于 Mojarra 中的 <h:inputText>
,可以在 HtmlBasicInputRenderer
.
中找到源代码
此设计允许渲染器完全控制转换步骤,并在必要时操纵此步骤。请注意,可以声明性地(通过 faces-config.xml
)覆盖(标准)组件的渲染器,而无需在视图中更改组件本身。另请注意,您问题中的术语 "custom renderer" 并不完全正确。它只是标准渲染器。我们只在 Web 应用程序提供自己的覆盖标准应用程序时才谈论 "custom renderer"。
众所周知,我们可以轻松编写自定义转换器并将其注册到组件中,如下所示:
<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 />
组件 class 是 UIInput
,它还有一个自定义的 com.sun.faces.renderkit.html_basic.TextRenderer
,因此 getRenderer(context)
returns 不是 [=22] =].因此,我们应该跳过 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
实际上,渲染器也是这样做的。另请参阅 Renderer#getConvertedValue()
.
Attempt to convert previously stored state information into an object of the type required for this component (optionally using the registered
Converter
for this component, if there is one). If conversion is successful, the new value should be returned from this method; if not, aConverterException
should be thrown.
对于 Mojarra 中的 <h:inputText>
,可以在 HtmlBasicInputRenderer
.
此设计允许渲染器完全控制转换步骤,并在必要时操纵此步骤。请注意,可以声明性地(通过 faces-config.xml
)覆盖(标准)组件的渲染器,而无需在视图中更改组件本身。另请注意,您问题中的术语 "custom renderer" 并不完全正确。它只是标准渲染器。我们只在 Web 应用程序提供自己的覆盖标准应用程序时才谈论 "custom renderer"。