如何使 JSF 自定义组件将自定义类型存储为其值?

How to make a JSF custom component to store a custom type as its value?

看起来很基本...

我有一个自定义的 JSF 组件及其关联的渲染器。渲染器执行 decodeencodeEnd.

decode 中,我通过 component.setSubmittedValue(ctx.getExternalContext().getRequestParameterMap().get(c.getClientId()));

成功重试了提交的值

encodeEnd 中,我主要创建标记,如果 component.getValue() 不为空,我将其内容插入标记中。到目前为止一切顺利。

问题是 getValue() 只能是 String。我有自定义 class 表示复合数据类型,我想将其用作组件的本地值。但不起作用 - JSF 转换为 String.

我还尝试使用 component.getAttributes() - 来自 decode 方法,我将我的自定义对象键入 private static final String someKey = "asd"。但是后来在 encodeEnd 地图上没有 value/key。

我希望此组件的用户能够在他们的支持 bean 中指定自定义数据类型,而不用担心 serialization/deserialization 到 client/server 之间的文本表示。大概我必须为此使用转换器?但是我怎样才能为自定义组件设置一个默认的和不可变的转换器呢?

这个问题有一个足够简单的解决方案。在渲染器 class 内部(如果直接使用,则直接进入组件 class):

@Override
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
    SomeCustomObject thing;
    //... do magic to create SomeCustomObject based on submittedValue
    return thing;
}

现在,每当对该组件调用 getValue() 时,SomeCustomObject 将被 returned,您可以安全地转换为它。同样在支持 bean 中可以使用 SomeCustomObject 作为类型。

另请注意,在实际渲染器中调用 component.getValue() 时,它也会 return SomeCustomObject,因此如果要恢复状态,则必须转换回其 String 表示形式.

有关更多详细信息,请参阅上面的@Kukeltje 的回答,并在此处检查如何对 primefaces 日历组件完成相同的操作:https://github.com/primefaces/primefaces/blob/master/src/main/java/org/primefaces/component/calendar/BaseCalendarRenderer.java

另一种更简洁明了的说明,请同时查看@BalusC 的回答。