12

動作するためにuserIdが必要なページがいくつかあるため、次のコードがあります。

userpage.xhtml

<!-- xmlns etc. omitted -->
<html>
<f:metadata>
    <f:viewParam name="userId" value="#{userPageController.userId}"/>
</f:metadata>
<f:view contentType="text/html">
<h:head>
</h:head>
<h:body>
    <h:form>
        <h:commandButton action="#{userPageController.doAction}" value="post"/>
    </h:form>
</h:body>
</f:view>

userPageController.java

@Named
@ViewScoped
public class userPageControllerimplements Serializable {
    private static final long serialVersionUID = 1L;

    @Inject protected SessionController sessionController;
    @Inject private SecurityContext securityContext;
    @Inject protected UserDAO userDAO;

    protected User user;
    protected Long userId;

    public UserPage() {
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        if(!FacesContext.getCurrentInstance().isPostback()){
            User u = userDAO.find(userId);
            this.userId = userId;
            this.user = u;
        }
    }

    public void doAction(){

    }

}

ただし、doActionが呼び出されると、URLのビューパラメータは表示されなくなります。Beanは、そのビュースコープの性質のために引き続き機能しますが、将来のナビゲーションの試みを台無しにします。検索すると、投稿後にviewパラメーターを残して、userpage.jsf?userId = 123と表示されているように見えますが、そうではありません。本当に意図された振る舞いは何ですか?

これに関連して、userIdを保持したい別のページに移動するときに、ビューパラメータの自動追加を実装しようとしました。他の人にとってはうまくいくようですが、私にとっては、ViewRootのuserIdは常にnullです。以下のコードは、viewparameterを取得するために使用されます(一時的に保存されたuserIdをナビゲーションに使用できることはわかっていますが、このソリューションの方がはるかに優れています)。

    String name = "userId";
    FacesContext ctx = FacesContext.getCurrentInstance();
    ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId);
    ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId);
    UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx);
    UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME);

    // Looking for a view parameter with the specified name
    UIViewParameter viewParam = null;
    for (UIComponent child : metadataFacet.getChildren()) {
        if (child instanceof UIViewParameter) {
            UIViewParameter tempViewParam = (UIViewParameter) child;
            if (name.equals(tempViewParam.getName())) {
                viewParam = tempViewParam;
                break;
            }
        }
    }

    if (viewParam == null) {
        throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId);
    }

    // Getting the value
    String value = viewParam.getStringValue(ctx);  // This seems to ALWAYS be null.

最後に考えたのは、setterメソッドはまだ機能しているようで、postでsetUserIdが正しい値で呼び出されるということです。

ビューパラメータがどのように機能するかを完全に誤解しましたか、それともここに何らかのバグがありますか?私のユースケースは非常に一般的であり、フレームワークで基本的なサポートが必要だと思います。

4

2 に答える 2

25

検索すると、投稿後にviewパラメーターを残して、userpage.jsf?userId = 123と表示されているように見えますが、そうではありません。本当に意図された振る舞いは何ですか?

この動作は正しいです。は、ビューパラメータのないアクションURLを含む<h:form>HTML要素を生成します。POSTリクエストは、まさにそのURLに送信されます。ビューパラメータをURLに保持する場合は、基本的に3つの方法があります。<form>

  1. いくつかのajax魔法を持ってきてください。

    <h:commandButton action="#{userPageController.doAction}" value="post">
        <f:ajax execute="@form" render="@form" />
    </h:commandButton>
    

    このようにして、最初に要求されたページ、したがってブラウザのアドレスバーの要求URLも常に同じままになります。

  2. 該当する場合(たとえば、ページ間ナビゲーションの場合)、それをGETリクエストにして、を使用しますincludeViewParams=true。あなたはこれのため<h:link>にそして<h:button>これのために使うことができます:

    <h:button outcome="nextview?includeViewParams=true" value="post" />
    

    ただし、これには、2.1.6より古いバージョンのMojarraでのELセキュリティエクスプロイトがあります。Mojarra2.1.6以降を使用していることを確認してください。2247号も参照してください。

  3. 自分のアクションURLの生成を制御し<h:form>ます。で仕事をするカスタムViewHandler(拡張するだけ)を提供します。ViewHandlerWrappergetActionURL()

    public String getActionURL(FacesContext context, String viewId) {
        String originalActionURL = super.getActionURL(context, viewId);
        String newActionURL = includeViewParamsIfNecessary(context, originalActionURL);
        return newActionURL;
    }
    

    実行するには、次のように登録しfaces-config.xmlます。

    <application>
        <view-handler>com.example.YourCustomViewHandler</view-handler>
    </application>
    

    これは、OmniFaces <o:form>が行っていることでもあります。includeViewParamsフォームのアクションURLにすべてのビューパラメータを含む追加の属性をサポートします。

    <o:form includeViewParams="true">
    

更新:現在のビューのビューパラメーターをプログラムで取得する(これは基本的に2番目の質問です)は、次のように実行する必要があります。

Collection<UIViewParameter> viewParams = ViewMetadata.getViewParameters(FacesContext.getCurrentInstance().getViewRoot());

for (UIViewParameter viewParam : viewParams) {
    String name = viewParam.getName();
    Object value = viewParam.getValue();
    // ...
}
于 2012-04-27T15:50:09.807 に答える
0

ソリューション1<f:ajax execute="@form" render="@form" />が機能するには、次のようなものも含める必要があります。

<f:param name="userId" value="#{userPageController.userId}"/>

<h:commandButton>?の内側

https://stackoverflow.com/a/14026995/811046で説明されているように

于 2016-11-11T13:59:37.737 に答える