サーブレット&JSPの基本|サーブレットのリダイレクト

ブラウザにもう一度リクエストしてもらう。リダイレクトで別の処理へ自然に移動させよう

サーブレットやJSPを使ったWebアプリケーションでは、ある処理を行ったあと、別の処理へ移動させたい場面があります。

たとえば、最初にリクエストを受け取るサーブレットでは細かい画面表示を行わず、別のサーブレットへ移動させたい場合があります。また、処理の入口だけを担当するサーブレットを用意し、実際の結果表示は別のサーブレットやJSPに任せたい場合もあります。

このように、処理を別の場所へ移す方法の1つがリダイレクトです。

リダイレクトでは、サーブレットがブラウザに対して、別のURLへリクエストし直してくださいという指示を返します。その指示を受け取ったブラウザは、指定されたURLへ自動的に再リクエストします。

利用者から見ると、途中でブラウザがもう一度リクエストしていることを強く意識する場面は多くありません。最終的には、リダイレクト先の処理結果が画面に表示されます。

この記事では、リダイレクトの基本的な流れ、sendRedirectによる実現方法、リダイレクト先の指定方法、そしてリダイレクト後にreturnを書く理由を順番に解説します。

リダイレクトとは

リダイレクトとは、ブラウザのリクエスト先を変更して、別の処理へ移動させる方法です。

最初にブラウザがあるサーブレットへリクエストを送ると、そのサーブレットは直接HTMLを返すのではなく、別のURLへリクエストし直すようにブラウザへ伝えます。

ブラウザはその指示を受け取り、自動的にリダイレクト先へ再リクエストします。そして、リダイレクト先のサーブレットやJSPが返した結果が画面に表示されます。

リダイレクトの基本的な流れ

順番処理
1ブラウザが最初のサーブレットへリクエストする
2サーブレットが別のURLへリクエストし直すように指示する
3ブラウザが指示されたURLへ自動的に再リクエストする
4リダイレクト先のサーブレットやJSPが処理を行う
5リダイレクト先の処理結果がブラウザに表示される

ポイントは、別の処理へ移動するのはサーバ内部だけの動きではなく、ブラウザが再リクエストする動きだということです。

図1:リダイレクトの基本的な流れ

この図から分かること

リダイレクトでは、最初にリクエストを受けたサーブレットが結果画面を直接返すとは限りません。

RedirectServletは、ブラウザに対してMenuServletへリクエストし直すように指示します。その指示を受け取ったブラウザは、自動的にMenuServletへ再リクエストします。

最終的に画面へ表示されるのは、RedirectServletの結果ではなく、リダイレクト先であるMenuServletが返した結果です。

リダイレクト先はブラウザがリクエストできる場所

リダイレクトでは、ブラウザが指定された先へ再リクエストします。

そのため、リダイレクト先にはブラウザがリクエストできる場所を指定します。

同じアプリケーション内のサーブレットへ移動することもできますし、JSPファイルへ移動することもできます。URLとして指定できる場所であれば、URL全体を使って指定することもできます。

リダイレクト先に指定できるもの

リダイレクト先指定の考え方
同じアプリケーション内のサーブレットクラスURLパターンを指定する
同じアプリケーション内のJSPファイルwebappからのパスを指定する
URLで表せる場所URL全体を指定する

同じstudyアプリケーション内のサーブレットへ移動する場合は、URL全体を書かずにURLパターンだけで指定できます。

たとえば、MenuServletへリダイレクトする場合は、MenuServletをリダイレクト先として指定できます。

sendRedirectでリダイレクトを行う

サーブレットでリダイレクトを行うには、HttpServletResponseインスタンスのsendRedirectを使います。

基本的な考え方は、responseに対してリダイレクト先を指定する、という形です。

sendRedirectの役割

項目内容
使うオブジェクトHttpServletResponseのresponse
使うメソッドsendRedirect
指定するものリダイレクト先
ブラウザの動き指定された先へ再リクエストする
画面表示リダイレクト先のレスポンスが表示される

sendRedirectを呼び出すと、サーブレットはブラウザへリダイレクトの指示を返します。

その後、ブラウザは指定されたURLへ自動的にリクエストし直します。

リダイレクト先の指定方法

リダイレクト先は、URL全体で指定することもできます。

たとえば、studyアプリケーション内のMenuServletへURL全体で指定する場合は、次のような考え方になります。

http://localhost:8080/study/MenuServlet

一方、リダイレクト先が同じアプリケーション内にある場合は、URL全体ではなく、URLパターンやwebappからのパスを使って指定できます。

同じアプリケーション内で指定するもの

リダイレクト先指定するもの
サーブレットクラスURLパターン
JSPファイルwebappからのパス

サーブレットクラスへリダイレクトする場合は、URLパターンを指定します。

JSPファイルへリダイレクトする場合は、webappからのパスを指定します。

指定方法の例

指定方法
URL全体で指定http://localhost:8080/study/MenuServlet
URLパターンで指定MenuServlet
JSPファイルのパスで指定result.jsp

同じアプリケーション内であれば、短く指定できるため、プログラムも読みやすくなります。

図2:sendRedirectでリダイレクト先を指定する

この図から分かること

サーブレットでリダイレクトを行うときは、response.sendRedirectを使います。

sendRedirectの引数には、ブラウザに再リクエストしてほしいリダイレクト先を指定します。同じアプリケーション内のサーブレットであれば、MenuServletのようにURLパターンを指定できます。

リダイレクトは、サーブレットが別のサーブレットを直接実行するというよりも、ブラウザに対して別のURLへ移動するように指示する処理です。

リダイレクトの動作を確認するプログラム

ここでは、リダイレクトの動作を確認するために、RedirectServletからMenuServletへリダイレクトするプログラムを考えます。

RedirectServletは、ブラウザからリクエストを受け取ります。しかし、自分では結果画面を出力しません。MenuServletへリクエストし直すようにブラウザへ指示します。

MenuServletは、リダイレクト先として実行され、おすすめメニューの結果画面をHTMLでレスポンスするものとします。

今回のプログラムの流れ

順番内容
1ブラウザでRedirectServletへリクエストする
2RedirectServletがMenuServletへのリダイレクトを指示する
3ブラウザがMenuServletへ自動的に再リクエストする
4MenuServletが結果画面をHTMLでレスポンスする
5ブラウザにおすすめメニュー結果画面が表示される

最初にアクセスするURLは次のとおりです。

http://localhost:8080/study/RedirectServlet

最終的に表示される結果画面は、RedirectServletではなくMenuServletが出力します。

図3:RedirectServletからMenuServletへリダイレクトする流れ

この図から分かること

RedirectServletは、ブラウザから最初のリクエストを受け取ります。

しかし、RedirectServletはHTMLを直接出力せず、MenuServletへリクエストし直すようにブラウザへ指示します。

ブラウザはその指示を受けてMenuServletへ再リクエストし、MenuServletが結果画面をHTMLで返します。リダイレクトでは、最初に呼ばれたサーブレットではなく、リダイレクト先が最終的な結果を出力する点を意識しましょう。

リダイレクトを行うサーブレットクラスを作成する

それでは、リダイレクトを行うRedirectServlet.javaを作成します。

このサーブレットは、doGetメソッドでリクエストを受け取り、MenuServletへリダイレクトします。

リダイレクトを行うサーブレットクラスの例

ファイル名: RedirectServlet.java

package servlet;

import java.io.IOException;

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("/RedirectServlet")
public class RedirectServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

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

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

このサーブレットで重要なのは、response.sendRedirect("MenuServlet");の部分です。

この処理によって、RedirectServletはブラウザへMenuServletにリクエストし直すように伝えます。MenuServletは同じアプリケーション内のサーブレットとして想定しているため、URL全体ではなくURLパターンで指定しています。

RedirectServlet.javaの動き

RedirectServlet.javaは、リクエストを受け取ってリダイレクトするだけのサーブレットです。

HTMLを出力する処理は書かれていません。画面を出す役割は、リダイレクト先のMenuServletが担当します。

RedirectServlet.javaの役割

処理内容
リクエストを受け取るブラウザからRedirectServletへアクセスされる
リダイレクトを指示するMenuServletへリクエストし直すようにブラウザへ伝える
処理を終了するreturnで後続処理を行わないようにする

このように、RedirectServletは入口として動き、結果表示はMenuServletに任せます。

リダイレクト先のサーブレットの例

このMenuServletは、次のリダイレクト指定と対応しています。

response.sendRedirect("MenuServlet");

ファイル名: MenuServlet.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("/MenuServlet")
public class MenuServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

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

        // おすすめメニューを設定
        String menu = "チキンカレー";

        // 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>おすすめメニュー</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>おすすめメニュー結果</h1>");
        out.println("<p>本日のおすすめメニューは「" + menu + "」です。</p>");
        out.println("</body>");
        out.println("</html>");
    }
}

URL全体でリダイレクト先を指定することもできる

RedirectServlet.javaでは、MenuServletというURLパターンを使ってリダイレクト先を指定しました。

同じアプリケーション内のサーブレットへ移動する場合は、このように短く書けます。

一方で、URL全体を指定してリダイレクトすることもできます。

たとえば、同じstudyアプリケーション内のMenuServletへURL全体で指定する場合は、次のURLをリダイレクト先として指定します。

http://localhost:8080/study/MenuServlet

指定方法の違い

指定方法リダイレクト先の例
URL全体で指定http://localhost:8080/study/MenuServlet
URLパターンで指定MenuServlet

同じアプリケーション内であれば、URLパターンで指定するほうが短く分かりやすいです。

ただし、URL全体で指定する方法も知っておくと、リダイレクトがブラウザに別のURLへ再リクエストさせる処理であることを理解しやすくなります。

sendRedirectの後にreturnを書く

RedirectServlet.javaでは、sendRedirectの直後にreturnを書いています。

sendRedirectを呼び出しても、サーブレットの処理がその場で自動的に完全終了するわけではありません。sendRedirectのあとに処理が書かれていれば、その処理が続けて実行されます。

今回の例では、sendRedirectの後ろに他の処理はありません。そのため、returnがなくてもすぐに問題が起こるとは限りません。

しかし、あとから処理を追加したときに、sendRedirectの後ろで別の処理が動いてしまうと、意図しない動作になる可能性があります。

returnを書く理由

理由内容
処理を明示的に終了するリダイレクト後に余計な処理を続けない
意図しない動作を防ぐ後続の処理が実行されることを避ける
将来の修正に備えるあとで処理を追加しても安全にしやすい
エラーを防ぎやすくするフォワードなど別の転送処理との衝突を避ける

リダイレクトの後にフォワード処理などが続いてしまうと、レスポンスの扱いが重なり、エラーの原因になることがあります。

そのため、sendRedirectを書いた直後にreturnを書き、ここで処理を終わらせる形にしておくのが一般的です。

リダイレクト後に後続処理を書かない

リダイレクトは、ブラウザに別のURLへ移動してもらうための指示です。

そのため、リダイレクトしたあとに、同じサーブレットでさらにHTMLを出力したり、別の転送処理を行ったりすると、処理の流れが分かりにくくなります。

避けたい処理

sendRedirectの後に書く処理起こりやすい問題
HTML出力どのレスポンスを返すのか分かりにくくなる
フォワード転送処理が重なり、エラーの原因になる
長い後続処理リダイレクト後の流れを追いにくくなる

リダイレクトを行ったら、その時点で処理を終える、と考えると安全です。

そのためにreturnを書いておくと、プログラムを読む人にも、ここで処理が終了することが伝わりやすくなります。

RedirectServletを実行する

RedirectServlet.javaを作成したら、動作を確認します。

実行方法は次の2つです。

方法内容
方法①ブラウザのアドレスバーにURLを入力してリクエストする
方法②Eclipseの実行機能でRedirectServlet.javaを実行する

ブラウザから実行する場合は、次のURLへアクセスします。

http://localhost:8080/study/RedirectServlet

このURLにアクセスすると、最初はRedirectServletへリクエストされます。

その後、RedirectServletがMenuServletへリダイレクトするため、ブラウザはMenuServletへ自動的に再リクエストします。

最終的に表示されるのは、MenuServletが出力したおすすめメニューの結果画面です。

ブラウザの表示例

実行時に確認するポイント

リダイレクトの動作を確認するときは、次の点を見ておくと理解しやすくなります。

確認項目内容
最初にアクセスするURLhttp://localhost:8080/study/RedirectServlet
RedirectServletの役割MenuServletへリダイレクトする
最終的に処理する先MenuServlet
結果画面を出すものMenuServlet
ブラウザの動き指示された先へ自動的に再リクエストする

リダイレクトでは、最初にリクエストしたサーブレットと、最終的に結果を出すサーブレットが異なることがあります。

ここを意識すると、処理の流れが分かりやすくなります。

リダイレクト先が正しくない場合

リダイレクト先の指定が間違っていると、ブラウザは誤ったURLへ再リクエストしてしまいます。

その結果、404ページが表示されることがあります。

たとえば、MenuServletへリダイレクトしたいのに、URLパターンを間違えて指定すると、ブラウザは存在しない場所へアクセスしてしまいます。

確認したいこと

確認項目内容
リダイレクト先の名前MenuServletなどの指定が正しいか
サーブレット側のURLパターン@WebServletの指定と合っているか
同じアプリケーション内かURLパターンで指定できる場所か
JSPの場合webappからのパスが正しいか

リダイレクト先がサーブレットであれば、@WebServletのURLパターンとsendRedirectの指定を見比べます。

リダイレクト先がJSPファイルであれば、webappからのパスが正しいかを確認します。

リダイレクトの基本として押さえること

リダイレクトは、サーブレットがブラウザへ別のURLを知らせ、ブラウザに再リクエストしてもらうしくみです。

フォワードとは違い、ブラウザがもう一度リクエストするところが特徴です。

リダイレクトの基本ポイント

ポイント内容
処理の特徴ブラウザに再リクエストさせる
使用するメソッドresponse.sendRedirect
リダイレクト先ブラウザがリクエストできる先
同じアプリケーション内のサーブレットURLパターンで指定できる
同じアプリケーション内のJSPwebappからのパスで指定できる
結果画面リダイレクト先が出力する
安全な書き方sendRedirectの直後にreturnを書く

RedirectServletがMenuServletへリダイレクトし、MenuServletが結果を表示する。この流れを押さえると、リダイレクトの動きがつかみやすくなります。

リダイレクトは、処理の転送方法を理解するうえで重要なしくみです。ブラウザが再リクエストするという特徴を意識しながら、実際に動かして確認してみましょう。