1

カスタム クラス オブジェクトをチェックボックス/コンボなどの MyFaces UI コンポーネントと一緒にバインドしようとしていますが、バッキングでゲッター/セッターを作成することにより、int/float/boolean/String/List<String> のような明示的な型を指定しません。豆。

したがって、私の場合、通常は次のようになります。

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

どこ:

  • ビーンはバッキングビーンです
  • 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>をどのように見つけることができますか? 私の場合、boolean、int、float、double、String、または List<String> にすることができます。

でも書くのはちょっと苦手

  1. 多くの「型へのキャストを試み、それが成功した場合、その型はあなたの型です」が、それが int か float/double かはわかりません。
  2. h:selectOneListbox を定義するときに、型をパラメーターまたは 2 番目のパラメーターとして指定する
  3. ???

どうすればこれを達成できますか?

編集: OK、リストは機能しません。しかし問題は、バッキング Bean の多くの単純な「ダミー」ゲッター/セッターへの書き込みを避けるために、私のビューで JSF UIComponents の値をある種の値ラッパーにバインドすることは良いことでしょうか?

したがって、「bean.get('property_name')」または「#{bean.myListValueHolder.data}」または同様の構文のように、Key (文字列であるプロパティ名) によって MyValueHolder にアクセスできる「1 つの」Bean を使用できます。 ?

EDIT2 : BalusC の質問に答え、その理由を説明します。

今のところ、このアプローチが良いものかどうかはわかりません。

私のデータは XML として提供されます。それを解析してkeyvalueペアとして保存します。私の UI 要素には、特定stateの (s) ( State-Enum {hidden、visible、disabled、enabled、hover、focus、active、...} からの EnumSet もあり、に格納されている特定の値に依存していValueHoldersます。必要なState( s) はRuleクラスで記述されており、EnumSetofStatematchesメソッドがあり、一致したためtrueに定義済みが適用されるかどうかをState返します。その一致に関連付けられた。RuleValueChangedListenersStateValueRulesValue

少なくともこれは私が考えた方法です、私はこれを行うことができます。したがって、ビューから値と ui-state を照会できます。具体的な値が変更された場合はStateUIComponentコールバックを呼び出してState、新しい css クラスをその特定のコンポーネントに追加/削除することができます。 Jクエリ。

まあ、ちょっと複雑またはかなりやり過ぎに聞こえますが、Java で UI コンポーネントを定義したいStatesので、Java からも変更できState、ビューで State-Rules が定義されていません。

4

2 に答える 2

3

JSFConverterはこれには適していません。これには習慣が必要ですELResolver。を拡張BeanELResolverしてオーバーライドgetType()し、具体的な実装を取得する必要がありますgetValue()。このようにして、最終的には. このようにして、データの強制/変換は JSF/EL によって自動的に行われます。setValue()ValueHoldervalue="#{bean.myStringValueHolder}".data

次の方法で、アプリケーションの起動時にカスタム EL リゾルバーを登録できますApplication#addELResolver()

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

ジェネリック型の理解に関しては、 が であり、 などの具体的な実装ValueHolderがあると仮定すると、 のコンストラクターでジェネリック型を抽出できます。abstract classStringValueHolder 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);
    }

}

このアプローチ全体がどのように役立つのだろうか。一見不必要なオーバーヘッドがいくつかあります。機能要件とは正確には何ですか?ゲッター/セッターボイラープレートを排除するだけですか? モデル オブジェクト (javabeans/entities/etc) だけを使用して、最終的にバッキング Bean にモデル プロパティを 1 つだけ持たないのはなぜですか? 毎回入力するのにうんざりしていませんか?少しまともなIDEはそれらを自動生成できます。さらに、プロパティ名のリストと数回のクリックに基づいて、完全な JavaBean クラスを自動生成できます。

于 2012-05-04T03:33:30.543 に答える
1

コンバーターのインスタンスを Bean に追加し、それを入力要素にバインドすると、型がわかります。このようにして、コンストラクターを介して変換するオブジェクトをコンバーターに渡し、単純なルックアップを実行することもできます。それほどハンサムではありませんが、うまくいくでしょう。

于 2012-05-04T00:25:53.527 に答える