サーブレット&JSPの基本|フォワードとリダイレクトの使い分け

内部で渡すならフォワード、ブラウザに行き直してもらうならリダイレクト。転送の違いを理解して正しく使い分けよう

サーブレットやJSPを使ったWebアプリケーションでは、ある処理のあとに別のサーブレットクラスやJSPファイルへ処理を移したい場面があります。

この処理の転送には、主にフォワードとリダイレクトがあります。

どちらも、最終的に別の処理の結果をブラウザに表示できるため、はじめは同じようなものに見えるかもしれません。しかし、実際の動きは大きく異なります。

フォワードは、同じWebアプリケーション内でサーバ側が処理を引き継ぐ方法です。ブラウザは転送されたことを意識せず、リクエストとレスポンスは1往復で完了します。

一方、リダイレクトは、サーブレットがブラウザに対して別のURLへリクエストし直すように指示する方法です。ブラウザはその指示を受け取り、リダイレクト先へもう一度リクエストします。そのため、リクエストとレスポンスは2往復になります。

この記事では、フォワードとリダイレクトの違い、使い分けの基本、転送後にアドレスバーのURLがどう変わるのか、そして両者の比較を整理して解説します。

フォワードとリダイレクトはどちらも処理を転送する

フォワードとリダイレクトは、どちらも処理を別の場所へ移すための方法です。

たとえば、あるサーブレットでリクエストを受け取ったあと、JSPファイルで結果画面を表示したい場合があります。また、あるサーブレットから別のサーブレットへ移動させたい場合もあります。

このようなときに、フォワードまたはリダイレクトを使います。

ただし、転送のしくみが違います。

転送方法の大まかな違い

転送方法大まかな動き
フォワードサーバ側で処理を別のサーブレットやJSPへ移す
リダイレクトブラウザに別のURLへリクエストし直してもらう

フォワードは、サーバ内部で処理を移すイメージです。

リダイレクトは、ブラウザに対して別の場所へ行き直してくださいと伝えるイメージです。

この違いが、リクエストとレスポンスの回数、転送できる範囲、アドレスバーに表示されるURLの違いにつながります。

フォワードの特徴

フォワードは、同じWebアプリケーション内のサーブレットクラスやJSPファイルへ処理を移す方法です。

ブラウザから見ると、最初にリクエストした先からレスポンスが返ってきたように見えます。途中で別のJSPファイルやサーブレットクラスに処理が移っていても、ブラウザはその内部処理を意識しません。

フォワードの主な特徴

項目内容
転送先同じWebアプリケーション内のサーブレットクラスやJSPファイル
リクエストとレスポンス1往復
ブラウザの再リクエスト行われない
アドレスバーのURL最初にリクエストしたURLのまま
基本的な使いどころサーブレットからJSPへ結果表示を依頼する場合

フォワードでは、リクエストがサーバ内でそのまま引き継がれます。

そのため、サーブレットで処理した結果をJSPに渡して表示するような流れに向いています。これ以降、サーブレットからJSPファイルへ処理を移して画面を表示する場合は、基本的にフォワードを使うと考えると整理しやすくなります。

リダイレクトの特徴

リダイレクトは、ブラウザに対して別のURLへリクエストし直すように指示する方法です。

最初にリクエストされたサーブレットは、結果画面を直接返すのではなく、リダイレクト先のURLをブラウザに伝えます。ブラウザはその指示に従い、自動的に別のURLへ再リクエストします。

リダイレクトの主な特徴

項目内容
転送先ブラウザがリクエストできるもの
リクエストとレスポンス2往復
ブラウザの再リクエスト行われる
アドレスバーのURLリダイレクト先のURLに変わる
基本的な使いどころ別のWebアプリケーションや外部のURLへ移動させる場合

リダイレクトでは、ブラウザが再度リクエストを行います。

そのため、同じWebアプリケーション内だけでなく、ブラウザがアクセスできる別のWebアプリケーションや外部サイトへ移動させることもできます。

図1:フォワードとリダイレクトの転送の違い

この図から分かること

フォワードとリダイレクトは、どちらも別の処理へ移るための方法ですが、転送の流れが異なります。

フォワードでは、ブラウザからのリクエストを受けたあと、サーバ側で別のサーブレットクラスやJSPファイルへ処理が移ります。ブラウザは再リクエストしないため、リクエストとレスポンスは1往復です。

リダイレクトでは、最初のサーブレットがブラウザへ別のURLを知らせます。そのあと、ブラウザがリダイレクト先へ再リクエストします。そのため、リクエストとレスポンスは2往復になります。

基本は転送元と転送先の関係で使い分ける

フォワードとリダイレクトの使い分けは、転送元と転送先のWebアプリケーションが同じかどうかで考えると分かりやすくなります。

転送先による使い分け

転送元と転送先の関係使う方法
同じWebアプリケーション内基本はフォワード
別のWebアプリケーションリダイレクト
外部サイトなどブラウザがアクセスする場所リダイレクト

転送元と転送先が別のWebアプリケーションの場合、フォワードは使えません。

フォワードは、同じWebアプリケーション内で処理を移すための方法だからです。

一方、リダイレクトはブラウザに再リクエストしてもらうしくみなので、ブラウザがアクセスできる先であれば転送できます。

同じWebアプリケーション内なら基本はフォワード

転送元と転送先が同じWebアプリケーション内にある場合は、フォワードとリダイレクトの両方を使えることがあります。

この場合、基本的にはフォワードを使います。

理由は、フォワードのほうがリクエストとレスポンスの往復が少ないためです。

同じアプリケーション内でフォワードを基本にする理由

理由内容
リクエストとレスポンスが1往復ブラウザが再リクエストしない
転送処理が比較的速い余分な往復が少ない
サーブレットからJSPへの表示依頼に向いている処理結果をJSPで表示しやすい

たとえば、サーブレットでリクエストを受け取り、処理を行い、その結果をJSPファイルで表示する場合は、フォワードを使うのが基本です。

この形は、MVCモデルに沿ったWebアプリケーションでもよく使う流れです。

サーブレットがコントローラとしてリクエストを受け取り、JSPがビューとして結果画面を表示する、という役割分担に合っているからです。

外部へ移動するならリダイレクト

転送先が別のWebアプリケーションや外部サイトの場合は、リダイレクトを使います。

フォワードは同じWebアプリケーション内の転送に使うものなので、別のWebアプリケーションへ処理を移すことはできません。

一方、リダイレクトはブラウザに別のURLへアクセスしてもらうため、外部のURLにも移動できます。

リダイレクトが必要になる場面

場面理由
別のWebアプリケーションへ移動するフォワードでは転送できない
外部サイトへ移動するブラウザに別URLをリクエストしてもらう必要がある
アドレスバーのURLを移動先に変えたいリダイレクトではURLが転送先に変わる

まずは、外部への転送はリダイレクト、内部への転送は基本フォワード、と覚えるとよいでしょう。

ただし、内部の転送でもリダイレクトを使う場面があります。その代表的な理由が、転送後のURLを変えたい場合です。

転送後のURLに違いが出る

フォワードとリダイレクトの違いは、ブラウザのアドレスバーに表示されるURLにも現れます。

転送後のURL

転送方法アドレスバーに表示されるURL
フォワード最初にリクエストしたURLのまま
リダイレクトリダイレクト先のURLに変わる

フォワードでは、サーバ内部で処理が移ります。ブラウザは別のURLへリクエストし直していないため、アドレスバーのURLは最初にリクエストしたURLのままです。

リダイレクトでは、ブラウザがリダイレクト先へ再リクエストします。そのため、アドレスバーのURLはリダイレクト先のURLに変わります。

図2:転送後のアドレスバーのURLの違い

この図から分かること

フォワードでは、画面の表示内容が転送先の結果になっても、ブラウザのアドレスバーは最初にリクエストしたURLのままです。

たとえば、Helloをリクエストし、その内部でGoodByeへフォワードした場合、画面にはGoodByeが出力した内容が表示されます。しかし、アドレスバーにはHelloのURLが残ります。

リダイレクトでは、ブラウザがGoodByeへ再リクエストするため、アドレスバーのURLもGoodByeに変わります。

フォワードではURLと表示内容がずれる場合がある

フォワードでは、転送後もアドレスバーのURLが変わりません。

これは、サーバ内部で処理が移っているだけで、ブラウザが別のURLへリクエストし直していないためです。

そのため、次のような状態になることがあります。

項目内容
アドレスバーhttp://localhost:8080/study/Hello
実際に表示している画面GoodByeが出力した結果

このように、URLはHelloなのに、画面内容はGoodByeというズレが起こる場合があります。

学習段階では少し分かりにくいかもしれませんが、このURLと画面内容のズレが不具合の原因になる場合があります。

そのような場合は、フォワードではなくリダイレクトを使うことで、ブラウザのURLを転送先に変えられます。

内部の転送でもリダイレクトを使う場合がある

同じWebアプリケーション内では、基本的にフォワードを使うと説明しました。

しかし、内部の転送でもリダイレクトを使う場合があります。

その理由の1つが、アドレスバーのURLを転送先のURLに変えたい場合です。

内部でもリダイレクトを使う可能性がある場面

場面理由
転送後のURLを画面内容と合わせたいURLと表示内容のズレを避ける
ブラウザに新しいURLとして扱わせたい再リクエストさせる必要がある
転送先のURLを明確に表示したいアドレスバーを更新したい

ここでは、具体的な細かい場面まで深く考えなくても大丈夫です。

まずは、内部の転送では基本的にフォワードを使うが、URLを変えたい場合などにはリダイレクトを使うこともある、と押さえておきましょう。

フォワードとリダイレクトの比較

フォワードとリダイレクトの違いを、表で整理してみましょう。

フォワードとリダイレクトの違い

比較項目フォワードリダイレクト
転送のしくみサーバ内部で処理を移すブラウザに再リクエストさせる
転送先サーブレットクラスまたはJSPファイルブラウザがリクエストできるものすべて
転送先のWebアプリケーション転送元と同じWebアプリケーションのみすべてのWebアプリケーションに転送できる
リクエストとレスポンス1往復2往復
アドレスバーのURLリクエスト時のまま変わらないリダイレクト先のURLに変わる
リクエストスコープの引き継ぎできるできない
基本的な使いどころ同じWebアプリケーション内で処理を渡す外部や別アプリケーションへ移動する、URLを変えたい

この表を見ると、フォワードとリダイレクトは、結果が似ていても内部の動きが大きく違うことが分かります。

特に重要なのは、同じWebアプリケーション内かどうか、アドレスバーのURLを変えたいかどうか、リクエストとレスポンスの往復が何回あるかです。

リクエストスコープの引き継ぎにも違いがある

フォワードとリダイレクトには、リクエストスコープの引き継ぎにも違いがあります。

フォワードでは、同じリクエストの中で処理が移るため、リクエストスコープを引き継ぐことができます。

一方、リダイレクトでは、ブラウザがリダイレクト先へ再リクエストします。つまり、別のリクエストになります。そのため、リクエストスコープは引き継がれません。

リクエストスコープの違い

転送方法リクエストスコープ
フォワード引き継げる
リダイレクト引き継げない

リクエストスコープについては、このあと詳しく学習する内容です。

現時点では、フォワードは同じリクエストの中で処理が移る、リダイレクトは新しいリクエストになる、という違いだけ押さえておくとよいでしょう。

図3:フォワードとリダイレクトの使い分けの考え方

この図から分かること

フォワードとリダイレクトを使い分けるときは、まず転送先が同じWebアプリケーション内かどうかを考えます。

同じWebアプリケーション内であれば、基本的にはフォワードを使います。特に、サーブレットで処理を行い、JSPで結果を表示する流れでは、フォワードが基本になります。

別のWebアプリケーションや外部のURLへ移動する場合は、リダイレクトを使います。

ただし、同じWebアプリケーション内でも、転送後にアドレスバーのURLを変えたい場合は、リダイレクトを使うことがあります。

フォワードとリダイレクトを試すサーブレットクラスを作成する

Hello サーブレットの例

以下のように作成できます。まずはフォワード版として、HelloからGoodByeへ処理を転送する形にしています。

ファイル名: Hello.java

package servlet;

import java.io.IOException;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/Hello")
public class Hello extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {

        // GoodByeへフォワード
        RequestDispatcher dispatcher =
                request.getRequestDispatcher("GoodBye");
        dispatcher.forward(request, response);
    }
}

ファイル名: GoodBye.java

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/GoodBye")
public class GoodBye extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response)
            throws ServletException, IOException {

        // HTMLを出力
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();

        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<meta charset=\"UTF-8\">");
        out.println("<title>GoodBye</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>GoodBye</h1>");
        out.println("<p>GoodByeサーブレットが出力した画面です。</p>");
        out.println("</body>");
        out.println("</html>");
    }
}

実行URLは次のとおりです。

http://localhost:8080/study/Hello

この場合、画面にはGoodBye.javaが出力した内容が表示されますが、フォワードなのでブラウザのアドレスバーは次のままです。

http://localhost:8080/study/Hello

ブラウザの表示例

リダイレクト版を試す場合は、Hello.javaのdoGetメソッド内を次のように変更します。

protected void doGet(HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {

    // GoodByeへリダイレクト
    response.sendRedirect("GoodBye");
    return;
}

リダイレクト版では、最終的にブラウザのアドレスバーが次のURLに変わります。

http://localhost:8080/study/GoodBye

ブラウザの表示例

まず覚えたい基本パターン

フォワードとリダイレクトの使い分けは、最初からすべての例外まで理解しようとすると難しく感じるかもしれません。

まずは、次の基本パターンを覚えておきましょう。

基本パターン

状況使う転送方法
サーブレットからJSPへ画面表示を依頼するフォワード
同じWebアプリケーション内で処理を移す基本はフォワード
別のWebアプリケーションへ移動するリダイレクト
外部サイトへ移動するリダイレクト
転送後のURLを変えたいリダイレクト

フォワードは、サーバ内部で処理を渡す方法です。

リダイレクトは、ブラウザに別のURLへ行き直してもらう方法です。

この違いを意識すると、どちらを使うべきか判断しやすくなります。

よくある整理の仕方

フォワードとリダイレクトは、次のように言い換えると理解しやすくなります。

転送方法イメージ
フォワードサーバ内部で担当者に処理を渡す
リダイレクトブラウザに別の窓口へ行き直してもらう

フォワードでは、ブラウザは最初に来た窓口のままだと思っています。しかし、内部では別の担当者が処理して結果を返しています。

リダイレクトでは、最初の窓口がブラウザに別の窓口へ行ってくださいと案内します。ブラウザは案内された窓口へ行き直し、そこで結果を受け取ります。

このように考えると、URLが変わるかどうか、リクエストが1回か2回かの違いも理解しやすくなります。

学習段階で意識したいこと

これからMVCモデルに沿ってWebアプリケーションを作るとき、サーブレットからJSPへ画面表示を任せる場面が多くなります。

その場合は、基本的にフォワードを使います。

ただし、リダイレクトも重要な転送方法です。外部へ移動したい場合や、転送後のURLをきちんと変えたい場合には、リダイレクトが必要になります。

使い分けの確認ポイント

確認項目考え方
転送先は同じアプリケーションか同じなら基本フォワード、別ならリダイレクト
URLを変えたいか変えたいならリダイレクト
リクエストを引き継ぎたいか引き継ぎたいならフォワード
ブラウザに再リクエストさせたいか再リクエストさせるならリダイレクト
サーブレットからJSPへ表示したいか基本はフォワード

フォワードとリダイレクトは、処理を転送するという点では似ています。

しかし、ブラウザが再リクエストするかどうか、URLが変わるかどうか、転送できる範囲がどこまでかという点で違いがあります。

まずは、内部は基本フォワード、外部はリダイレクト、URLを変えたいときはリダイレクト、という考え方に慣れていきましょう。