web-dev-qa-db-ja.com

リダイレクトとナビゲーション/転送の違いは何ですか?何を使用するのですか?

JSFのナビゲーションの違いは何ですか

FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, url);

そしてリダイレクト

HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.sendRedirect(url);

そして、いつ何を使用するかを決定する方法は?

ナビゲーションの問題は、faces-redirect=trueがナビゲーションURLのクエリ文字列に追加されない限り、ページURLが変更されないことです。ただし、私の場合、プレーンHTMLページのような非JSFページにリダイレクトする場合、faces-redirect=trueを追加するとエラーがスローされます。

そして、別のオプションは JSF 2.0リダイレクトエラー でBalusCが提案したとおりです。

32
ad-inf

まず、「リダイレクト」という用語は、Web開発の世界では、クライアントに新しいGETを送信する必要がある新しいURLを含むLocationヘッダーのみを含む空のHTTP応答をクライアントに送信するアクションです。要求。だから基本的に:

  • クライアントは、HTTP要求を_somepage.xhtml_に送信します。
  • サーバーは_Location: newpage.xhtml_ヘッダーでHTTP応答を送り返します
  • クライアントは、HTTP要求を_newpage.xhtml_に送信します(これはブラウザーのアドレスバーに反映されます!)
  • サーバーは、_newpage.xhtml_のコンテンツでHTTP応答を送り返します。

Webbrowserの組み込み/アドオン開発者ツールセットで追跡できます。 Chrome/IE9/FirebugでF12を押し、[ネットワーク]セクションで確認してください。

JSFナビゲーションハンドラーはリダイレクトを送信しません。代わりに、ターゲットページのコンテンツをHTTP応答として使用します。

  • クライアントは、HTTP要求を_somepage.xhtml_に送信します。
  • サーバーは、_newpage.xhtml_のコンテンツでHTTP応答を送り返します。

ただし、元のHTTP要求は_somepage.xhtml_であったため、ブラウザーのアドレスバーのURLは変更されません。 基本的なサーブレットAPI に精通している場合、これは RequestDispatcher#forward() と同じ効果があることを理解する必要があります。


JSFフードの下からHttpServletResponseをプルし、その上でsendRedirect()を呼び出すことが適切な使用方法であるかどうかについては、いいえ、それは適切な使用法ではありません。サーバーログはIllegalStateExceptionsで乱雑になります。この方法では、応答処理の制御をすでに引き継いだことをJSFに伝えておらず、JSFはデフォルトの応答処理ジョブを行うべきではありません。実際には、後で FacesContext#responseComplete() を実行する必要があります。

また、マネージドBeanのようなJSFアーティファクトの_javax.servlet.*_パッケージから何かをインポートする必要があるときはいつでも、コードを書くのを絶対にやめ、本当に正しい方法で物事を行っているかどうかを自問してください。あなたが達成しようとしていることや、タスクが実際にJSFマネージドBeanに属している場合は、すでに「標準JSF方法」ではありません(つまり、単純な サーブレットフィルタ がより良い場所でした)。

JSFでリダイレクトを実行する適切な方法は、アクションの結果に_faces-redirect=true_クエリ文字列を使用することです。

_public String submit() {
    // ...
    return "/newpage.xhtml?faces-redirect=true";
}
_

または、 ExternalContext#redirect() を使用して、ajaxやprerenderリスナーメソッドなどのアクションメソッド内にいない場合:

_public void listener() throws IOException {
    // ...
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + "/newpage.xhtml");
}
_

(はい、IOExceptionに_try-catch_を付ける必要はありません。例外をthrowsに通すだけで、サーブレットコンテナはそれを処理する)

または、 NavigationHandler#handleNavigation() を使用して、特定のケースで、XMLナビゲーションケースおよび/または組み込みリスナーでカスタムナビゲーションハンドラーを使用している場合:

_public void listener() {
    // ...
    FacesContext fc = FacesContext.getCurrentInstance();
    NavigationHandler nh = fc.getApplication().getNavigationHandler();
    nh.handleNavigation(fc, null, "/newpage.xhtml?faces-redirect=true");
}
_

「プレーンHTML」ファイルのナビゲーションハンドラーが失敗する理由については、ナビゲーションハンドラーはJSFビューのみを処理でき、他のファイルは処理できないためです。 ExternalContext#redirect()を使用する必要があります。

こちらもご覧ください:

79
BalusC