forward()
とsendRedirect()
の概念的な違いは何ですか?
requestDispatcher-forward()メソッド
forward
メソッドを使用すると、リクエストはさらに処理するために同じサーバー内の別のリソースに転送されます。
forward
の場合、Webコンテナーはすべての処理を内部で処理し、クライアントまたはブラウザーは関与しません。
forward
がrequestDispatcher
objectで呼び出されると、リクエストオブジェクトとレスポンスオブジェクトを渡すため、リクエストを処理する新しいリソースに古いリクエストオブジェクトが存在します。視覚的には、転送されたアドレスを見ることができず、透過的です。
forward()
メソッドの使用は、sendRedirect
よりも高速です。Forwardを使用してリダイレクトし、新しいリソースで同じデータを使用する場合、利用可能なリクエストオブジェクトがあるので、
request.setAttribute()
を使用できます。SendRedirect
sendRedirect
の場合、要求は別のリソース、別のドメイン、またはさらに処理するために別のサーバーに転送されます。
sendRedirect
を使用すると、コンテナはリクエストをクライアントまたはブラウザに転送するため、sendRedirect
メソッド内で指定されたURLはクライアントへの新しいリクエストとして表示されます。
sendRedirect
呼び出しの場合、古いリクエストとレスポンスオブジェクトはブラウザによって新しいリクエストとして扱われるため失われます。アドレスバーに、リダイレクトされた新しいアドレスが表示されます。透明ではありません。
sendRedirect
は、完全に新しい要求が作成され、古い要求オブジェクトが失われるため、余分なラウンドトリップが1回必要になるため、遅くなります。 2つのブラウザー要求が必要です。ただし、
sendRedirect
では、使用する場合はセッションにデータを保存するか、URLと共に渡す必要があります。どちらが良いですか?
その方法がより有用なシナリオに依存します。
制御が新しいサーバーまたはコンテキストへの転送であり、完全に新しいタスクとして扱われる場合は、
sendRedirect
に進みます。一般に、ブラウザがWebページをリロードしたときに操作を安全に繰り返すことができ、結果に影響しない場合は、転送を使用する必要があります。
Web開発の世界では、「リダイレクト」という用語は、クライアントが新しいGETリクエストを送信する必要がある新しいURLを含むLocation
ヘッダーのみを含む空のHTTP応答をクライアントに送信する行為です。だから基本的に:
some.jsp
にHTTPリクエストを送信します。Location: other.jsp
ヘッダーでHTTP応答を送り返しますother.jsp
にHTTPリクエストを送信します(これはブラウザーのアドレスバーに反映されます!)other.jsp
のコンテンツでHTTP応答を送り返します。Webブラウザの組み込み/アドオン開発者ツールセットを使用して追跡できます。 Chrome/IE9/FirebugでF12を押し、[ネットワーク]セクションで確認してください。
まさに上記はsendRedirect("other.jsp")
によって達成されます。 RequestDispatcher#forward()
はリダイレクトを送信しません。代わりに、ターゲットページのコンテンツをHTTP応答として使用します。
some.jsp
にHTTPリクエストを送信します。other.jsp
のコンテンツでHTTP応答を送り返します。ただし、元のHTTP要求はsome.jsp
であったため、ブラウザのアドレスバーのURLは変更されません。
RequestDispatcher
は、MVCパラダイムや、JSPを直接アクセスから隠したい場合に非常に役立ちます。 JSPを/WEB-INF
フォルダーに配置し、要求を制御、前処理、および後処理するServlet
を使用できます。 /WEB-INF
フォルダー内のJSPはURLで直接アクセスできませんが、Servlet
はRequestDispatcher#forward()
を使用してアクセスできます。
たとえば、/WEB-INF/login.jsp
にあるJSPファイルと、url-pattern
の/login
にマッピングされるLoginServlet
を使用できます。 http://example.com/context/login
を呼び出すと、サーブレットのdoGet()
が呼び出されます。あなたは何でもできます 前そこにあるものを処理し、最後にforwardリクエストを次のように:
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
フォームを送信するとき、通常はPOST
を使用します:
<form action="login" method="post">
これにより、サーブレットのdoPost()
が呼び出され、任意の操作を実行できます 役職そこにあるものを処理します(検証、ビジネスロジック、ユーザーのログインなど)。
エラーがある場合、通常はリクエストを同じページにforwardして、入力フィールドの隣などにエラーを表示します。これにはRequestDispatcher
を使用できます。
POST
が成功した場合、通常、リクエストをredirectして、ユーザーが更新したときにリクエストが再送信されないようにします。要求(例:F5を押す、または履歴に戻る)。
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
response.sendRedirect("home"); // Redirects to http://example.com/context/home after succesful login.
} else {
request.setAttribute("error", "Unknown login, please try again."); // Set error.
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to same page so that you can display error.
}
redirectは、指定されたURLで新しいGET
リクエストを発行するようクライアントに指示します。リクエストを更新すると、リダイレクトされたリクエストのみが更新され、最初のリクエストは更新されません。これにより、「二重送信」や混乱、ユーザーエクスペリエンスの低下を回避できます。これは POST-Redirect-GET
pattern とも呼ばれます。
RequestDispatcher
インターフェースを使用すると、サーバー側のフォワード/インクルードを実行できますが、 sendRedirect()
はクライアント側のリダイレクトを実行します。クライアント側のリダイレクトでは、サーバーは302
(一時リダイレクト)のHTTPステータスコードを返送します。これにより、Webブラウザーはリダイレクトされた場所のコンテンツに対して新しいHTTP GET
要求を発行します。対照的に、 RequestDispatcher
インターフェイスを使用する場合、新しいリソースへのインクルード/転送は完全にサーバー側で処理されます。
SendRedirect()
は、サーバー間でコンテンツを検索します。コンテンツのURLを送信することでブラウザを推測する必要があるため、時間がかかります。ブラウザは同じサーバー内または別のサーバー内のコンテンツに対する新しいリクエストを作成します。
RquestDispatcher
は、サーバー内のコンテンツを検索するためのものです。サーバー側のプロセスであり、SendRedirect()
メソッドと比較して高速です。ただし、必要な日付またはコンテンツを検索しているサーバーのブラウザーを特定することはなく、URLタブのURLを変更するようブラウザーに要求することもありません。そのため、ユーザーにはほとんど不都合がありません。
これらの方法のいずれかは、あなたが何をしたいかに応じて、「より良い」、すなわちより適切であるかもしれません。
サーバー側のリダイレクトは、ブラウザを往復せずに別のページからデータを取得する限り高速です。ただし、ブラウザに表示されるURLは元のアドレスのままなので、そこに少し矛盾が生じています。
クライアント側のリダイレクトは、完全に別のサーバーに送信したり、プロトコルを変更したり(たとえば、HTTPからHTTPSにしたり)したり、その両方を行うことができる限り、より用途が広くなります。そして、ブラウザは新しいURLを認識します。ただし、サーバーとクライアントの間で余分な時間がかかります。
別のドメインに制御を移す必要がある場合、またはタスクの分離を達成する必要がある場合は、技術的にリダイレクトを使用する必要があります。
たとえば、支払いアプリケーションでは、最初にPaymentProcessを実行し、次にdisplayPaymentInfoにリダイレクトします。クライアントがブラウザを更新すると、displayPaymentInfoのみが再度実行され、PaymentProcessは繰り返されません。ただし、このシナリオでforwardを使用すると、PaymentProcessとdisplayPaymentInfoの両方が順番に再実行され、データが不確定になる可能性があります。
他のシナリオでは、sendRedirectよりも高速であるため、forwardの使用が効率的です。
ディスパッチャを使用すると、リクエストデータをあるサーブレットから別のサーブレットに移動できます。リクエストディスパッチャの代替手段はリダイレクトの送信ですが、新しいリクエストが送信されるたびに、リダイレクトがネットワーク内に戻ってくるたびに、サーバ内でリクエストディスパッチャが発生します。
例
Javaのサーブレットディスパッチャリクエストディスパッチャの概念を簡単な例で理解しましょう。 servlet1、servlet2およびServlet3という名前の3つのサーブレットがある状況を考えます。ディスパッチャーを使用しない場合、servlet1を要求するたびに、サーバーはservlet1に制御を渡します。その後、servlet2を要求すると、サーブレット1からサーバーに制御が戻り、servlet2に渡されます。この場合、サーバーがインドにあり、サーブレットがアメリカから要求されている場合、2番目の要求ではサーバー(インド)に戻り、サーブレット(アメリカ)に戻る必要があります。リクエストとレスポンスの間にトラフィックが多い場合、このオプションは適切ではありません。この問題の解決策はディスパッチャーです。
Javaのサーブレットディスパッチャ同じケースで、サーバ内でディスパッチャを使用すると、サーバに戻らず、ネットワークに関与することなく、servlet1からservlet2に制御が渡されます。この概念は、サーブレットチェーンとも呼ばれます。 servlet1からservlet2、Servlet2からServlet3のサーブレットリクエストのチェーンを作成し、サーバーがservlet3からデータを取得するため、これはサーブレットチェーンとして知られています。
データの受け渡し
サーブレットチェーンでは、制御が渡されるだけでなく、データが1つのサーブレットから他のサーブレットに移動します。これは、リダイレクトの送信に比べて大きな利点です。送信リダイレクトでは、新しいデータを取得するたびに、すべてのリクエストが新しいリクエストになります。
Servlet1には、servlet3によって実行される必要があるリクエストパラメータがあり、その後、データがservlet1からservlet2に移動し、その後servlet2からservlet3に移動できると考えてください。
リクエストの寿命は非常に短く、レスポンスを取得するとすぐにリクエストは終了しますが、リクエストの寿命はサーブレット間で保持できます。これにより、多くのサーブレットでタスクを分割できます。
短所
ほとんどの場合、ディスパッチャは効率的ですが、データが大きい場合やデータがまったく必要ない場合、または入稿が少ない場合は、リダイレクトを効率的に送信します。
Request Dispatcherは、Webリソースから別のWebリソースに要求または応答をディスパッチするために使用されるインターフェイスです。主に2つのメソッドが含まれています。
request.forward(req,res)
:このメソッドは、あるWebリソースから別のリソースにリクエストを転送するために使用されます。つまり、あるサーブレットから別のサーブレットへ、またはあるWebアプリケーションから別のWebアプリケーションへ。
response.include(req,res)
:このメソッドは、あるサーブレットから別のサーブレットへの応答を含むために使用されます
注:Request Dispatcherを使用すると、同じサーバー内で要求または応答を転送または含めることができます。
request.sendRedirect()
:これを使用することにより、異なるサーバー間で要求または応答を転送または含めることができます。この場合、クライアントはページをリダイレクトしている間に暗示を取得しますが、上記のプロセスではクライアントは暗示を取得しません