2

jsf 2 ビュー スコープの理解プロセスをさらに進めていくと、再び問題が発生します。

作成された複合コンポーネントのバインドされたオブジェクトの複数のインスタンスがあり、設定値が「正しい」ものを対象としていないようです。

ビュースコープのBeanからセッションスコープのBeanを自動インスタンス化するのと同じ初期設定があります

次に、複合コンポーネントを作成しました。

<composite:interface componentType="helloWidget">

</composite:interface>

<composite:implementation>
    <h:outputText value="Visible state of this composite component: #{cc.visibleState}"/>
</composite:implementation>

およびそのJava対応

@FacesComponent(value = "helloWidget")
public class HelloWidget extends UINamingContainer implements Serializable {

    private static final long serialVersionUID = 2L;
    private boolean visible;

    public void show() {
        System.out.println("Setting visible state to true " + this);
        visible = true;
    }

    public void hide() {
        System.out.println("Setting visible state to false " + this);
        visible = false;
    }

    public String getVisibleState() {
        System.out.println("Getting visible state of " + this + "(" + visible + ")");
        return String.valueOf(visible);
    }
}

次に、ViewBean.java をアップグレードしました

private HelloWidget helloWidget;
private boolean visible;

public String getVisibleState() {
    return String.valueOf(visible);
}

public void actionShow(ActionEvent ae) {

    visible = true;
    helloWidget.show();
}

public void actionHide(ActionEvent ae) {

    visible = false;
    helloWidget.hide();
}

public HelloWidget getHelloWidget() {
    return helloWidget;
}

public void setHelloWidget(HelloWidget helloWidget) {
    this.helloWidget = helloWidget;
}

そして私のhello.xhtml:

<f:view>
    <h:form>
        <h:outputText value="View-scoped bean visible value: #{viewBean.visibleState}"/>
        <br/>
        <mycc:helloWidget binding="#{viewBean.helloWidget}"/>
        <br/>
        <h:commandButton value="Show" actionListener="#{viewBean.actionShow}"/>
        <h:commandButton value="Hide" actionListener="#{viewBean.actionHide}"/>
    </h:form>
</f:view>

表示/非表示ボタンを押すと、ビュー スコープ Bean の「visible」プロパティの値が期待どおりに変更されます。HelloWidget プロパティの「visible」値も変更されますが、ページが表示されると、別の HelloWidget インスタンスが表示され、visible が (デフォルト) false に設定されます。

ここで何が間違っていますか?複合コンポーネントをバインドする方法に問題はありますか?

4

1 に答える 1

1

コンポーネントは、ビューの構築/復元中にインスタンス化されます。したがって、それらは基本的にリクエストスコープです。ビュー スコープに保持したい状態はすべて、JSF ビュー状態に格納する必要があります。通常のアプローチは、ビュー スコープの状態を表すプロパティのゲッター/セッターを に委譲させることUIComponent#getStateHelper()です。

したがって、これは次のようにする必要があります。

@FacesComponent(value = "helloWidget")
public class HelloWidget extends UINamingContainer implements Serializable {

    private static final long serialVersionUID = 2L;

    public void show() {
        setVisible(true);
    }

    public void hide() {
        setVisible(false);
    }

    public Boolean getVisible() {
        return (Boolean) getStateHelper().eval("visible");
    }

    public void setVisible(Boolean visible) {
        getStateHelper().put("visible", visible);
    }
}

ただし、この問題に関連しない別の潜在的な問題がありbindingます。ビュー スコープ Bean プロパティで使用すると、ビュー スコープ Bean 自体がすべてのリクエスト中に再作成されます。bindingこの属性は細心の注意を払って使用してください。この問題には、JSF2 Facelets の JSTL で既に説明されているのと同じ根拠があります...理にかなっていますか? .

于 2013-03-21T16:46:44.360 に答える