1

我正在尝试将自定义类对象与 MyFaces UI 组件(如复选框/组合等)绑定在一起,但没有通过在支持中创建 getter/setter 来提供像 int/float/boolean/String/List<String> 这样的显式类型豆。

所以在我的情况下,它通常看起来像这样:

<h:selectOneListbox id="mylist" value="#{bean.myListValueHolder.data}"
    converter="myValueConverter">
    ...
</h:selectOneListbox>

在哪里:

  • bean 是支持 bean
  • myListValueHolder 的类型为 MyValueHolder<T>
  • 数据类型为 <T>

我正在尝试为其使用自定义转换器和此类签名:

public class MyValueHolder<T extends Comparable<T>> extends Node<T> {
....

MyValueHolder 有这个方法:

public T getData() {
...
public void setData(Object data) {
...
public void setData(T data) {
...

我的转换器:

public Object getAsObject(FacesContext fc, UIComponent c, String value) {
...

问题:如何找出在运行时作为传递的类型<T>?在我的例子中,它可以是布尔值、int、float、double、String 或 List<String>。

但我有点不喜欢写

  1. 很多“尝试转换为一个类型,如果它成功,它就是你的类型”,但不确定它是 int 还是 float/double。
  2. 在我定义我的 h:selectOneListbox 时将类型作为参数或作为第二个参数
  3. ???

我怎样才能做到这一点?

编辑:好的,列表不起作用。但问题是,在我看来,将 JSF UIComponents 中的值绑定到某种值包装器以避免在我的支持 bean 中写入许多简单的“虚拟”getter/setter 是否有好处?

所以我可以使用“一个”bean,它可以通过键(属性名称是一个字符串)访问 MyValueHolder,如“bean.get('property_name')”或“#{bean.myListValueHolder.data}”或类似的语法?

EDIT2:回答 BalusC 问题并解释原因。

至于现在,我不确定这种方法是否好。

我的数据以 XML 形式出现,我对其进行解析以将其另存为key,value对。我的 UI 元素也有一个特定state的(s)(来自State-Enum {hidden, visible, disabled, enabled, hover, focus, active, ...} 的 EnumSet,它依赖于存储在中的特定值ValueHolders。所需的依赖项State( s)在一个类中描述,该类Rule具有一个EnumSetofState和一个matches方法,true如果定义State应被应用,则返回,因为Rule匹配。与该匹配相关的。ValueChangedListenersStateValueRulesValue

至少我是这么想的,我可以做到。所以我可以从我的视图中查询值和 ui-state,如果一些具体的值发生变化,这反过来可能会改变StateUIComponent可以调用回调并取决于新的State添加/删除一个新的 css 类到该特定组件通过查询。

好吧,听起来有点复杂或有点矫枉过正,但我​​想States用 Java 定义我的 UI 组件,所以我也可以State从 Java 更改它,而不是在视图中定义状态规则。

4

2 回答 2

3

JSFConverter不适合这种情况。你需要一个定制ELResolver。扩展BeanELResolver和覆盖getType()getValue()并且setValue()您应该在其中获取具体ValueHolder实现。这样你最终可以得到像value="#{bean.myStringValueHolder}"没有.data. 这样,数据强制/转换将由 JSF/EL 自动完成。

您可以通过以下方式在应用程序启动时注册自定义 EL 解析器Application#addELResolver()

FacesContext.getCurrentInstance().getApplication().addELResolver(new ValueHolderELResolver());

至于计算泛型类型,假设它ValueHolder是 anabstract class并且您有诸如此类的具体实现StringValueHolder extends ValueHolder<String>,那么您将能够在 的构造函数中提取泛型类型ValueHolder

public abstract class ValueHolder<T extends Comparable<T>> extends Node<T> {

    private Class<T> type;
    private T data;

    @SuppressWarnings("unchecked")
    public ValueHolder() {
        this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Class<T> getType() {
        return type;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public void setData(Object data) {
        this.data = type.cast(data);
    }

}

我只是想知道整个方法如何有用。有一些看似不必要的开销。功能需求究竟是什么?它只是在消除 getter/setter 样板?为什么不只使用模型对象(javabeans/entities/etc),这样您最终在支持 bean 中只有一个模型属性?是否厌倦了每次都输入它们?有点像样的 IDE 可以自动生成它们。更重要的是,可以根据属性名称列表和单击几下自动生成完整的 javabean 类。

于 2012-05-04T03:33:30.543 回答
1

您可以将转换器的实例添加到您的 bean 并将其绑定到您的输入元素,然后您就知道类型了。这样,您还可以通过构造函数将要转换的对象传递给转换器并执行简单的查找。不是那么帅,但它会工作。

于 2012-05-04T00:25:53.527 回答