サーブレット&JSPの基本|セッションスコープを使ったWebアプリ作成

入力、確認、完了の画面をつなぐ。セッションスコープでリクエストをまたぐWebアプリを作ろう

リクエストスコープは、サーブレットからJSPへ一時的にデータを渡すときに便利なスコープです。

しかし、リクエストスコープに保存したインスタンスは、レスポンスが返ると利用できなくなります。そのため、次のリクエストでも同じインスタンスを使いたい場合には向いていません。

そこで使うのがセッションスコープです。

セッションスコープにインスタンスを保存すると、レスポンス後もデータを残すことができます。そのため、入力画面、確認画面、完了画面のように、複数の画面をまたいで同じ情報を使いたい場合に役立ちます。

この記事では、セッションスコープを使って研修コース申込機能を作成します。利用者が申込ID、確認コード、氏名を入力し、確認画面で内容を確認してから、完了画面へ進むアプリケーションです。

入力された申込情報は、サーブレットでJavaBeansとして作成し、セッションスコープに保存します。確認画面ではセッションスコープから申込情報を取得して表示します。登録実行時にも、セッションスコープから同じインスタンスを取得して、登録処理を担当するモデルに渡します。

作成するWebアプリケーションの流れ

今回作成する研修コース申込機能は、次の3つの画面で構成します。

画面遷移

画面内容
研修コース申込入力画面申込ID、確認コード、氏名を入力する
研修コース申込確認画面入力した申込IDと氏名を確認する
研修コース申込完了画面申込完了メッセージを表示する

最初に、ブラウザからTrainingEntryServletへアクセスします。

すると、入力画面であるtrainingEntryForm.jspへフォワードされます。利用者が情報を入力して確認ボタンをクリックすると、POSTリクエストでTrainingEntryServletへ送信されます。

サーブレットは入力内容をもとにTrainingEntryインスタンスを作成し、セッションスコープに保存します。その後、確認画面であるtrainingEntryConfirm.jspへフォワードします。

確認画面で申込ボタンをクリックすると、action=doneというリクエストパラメータ付きでTrainingEntryServletへGETリクエストが送られます。サーブレットはセッションスコープから申込情報を取得し、TrainingEntryLogicに登録処理を依頼します。最後に、不要になった申込情報をセッションスコープから削除し、完了画面へフォワードします。

図1:研修コース申込機能の画面遷移

この図から分かること

このアプリケーションでは、入力画面、確認画面、完了画面の順に画面が進みます。

入力画面で送信された申込情報は、確認画面だけでなく、完了処理を行うときにも必要です。確認画面から完了処理へ進むときは、別のリクエストになります。

そのため、申込情報をリクエストスコープではなくセッションスコープに保存します。セッションスコープに保存しておけば、入力後の確認画面でも、確認画面から申込を実行するときでも、同じTrainingEntryインスタンスを利用できます。

作成するファイル

今回のアプリケーションでは、MVCモデルに沿って6つのファイルを作成します。

作成するファイル一覧

ファイル種類役割
TrainingEntry.javaモデル JavaBeans申込ID、氏名、確認コードを持つ
TrainingEntryLogic.javaモデル 処理クラス申込処理を行う
TrainingEntryServlet.javaコントローラ サーブレットリクエストを受け取り、画面遷移と処理を制御する
trainingEntryForm.jspビュー JSP申込入力画面を表示する
trainingEntryConfirm.jspビュー JSP申込確認画面を表示する
trainingEntryDone.jspビュー JSP申込完了画面を表示する

TrainingEntry.javaは、入力された申込情報をまとめて保持するJavaBeansです。

TrainingEntryLogic.javaは、申込処理を担当するモデルです。今回は学習用のサンプルなので、ファイルやデータベースへの登録は行わず、登録できたものとしてtrueを返します。

TrainingEntryServlet.javaは、リクエストを受け取り、入力画面、確認画面、完了画面のどこへ進むかを判断します。

3つのJSPファイルは、画面表示を担当します。

MVCモデルとしての構成

今回の研修コース申込機能は、MVCモデルの形で作成します。

MVCモデルでの役割

MVCの要素今回の担当内容
ModelTrainingEntry.java
TrainingEntryLogic.java
申込情報の保持と申込処理を担当する
ViewtrainingEntryForm.jsp
trainingEntryConfirm.jsp
trainingEntryDone.jsp
入力画面、確認画面、完了画面を表示する
ControllerTrainingEntryServlet.javaリクエストを受け取り、処理と画面遷移を制御する

MVCモデルでは、データ、処理、表示、制御を分けて作ります。

今回のアプリケーションでは、TrainingEntryServletが中心となり、必要に応じてモデルを使い、表示するJSPを切り替えます。

図2:セッションスコープを使った研修コース申込機能の構成

この図から分かること

このアプリケーションでは、TrainingEntryServletがコントローラとしてリクエストを受け取ります。

入力画面から送信された申込情報は、TrainingEntryインスタンスとして作成され、セッションスコープに保存されます。確認画面では、そのTrainingEntryインスタンスをセッションスコープから取得して表示します。

確認画面で申込を実行すると、TrainingEntryServletは再び呼び出されます。このときも、セッションスコープからTrainingEntryインスタンスを取得できるため、登録処理に利用できます。

登録処理が終わったら、不要になったTrainingEntryインスタンスをセッションスコープから削除します。

処理全体の流れ

今回のアプリケーションは、3つのリクエストで動きます。

リクエスト① 申込入力画面を表示する

順番内容
1ブラウザからTrainingEntryServletへGETリクエストを送る
2TrainingEntryServletのdoGetメソッドが実行される
3actionの値がnullなので、申込開始と判断する
4trainingEntryForm.jspへフォワードする
5申込入力画面が表示される

最初にブラウザでアクセスするURLは次のようになります。

http://localhost:8080/study/TrainingEntryServlet

この時点では、actionというリクエストパラメータは送信しません。そのため、doGetメソッドではactionの値がnullになります。

リクエスト② 入力内容を確認する

入力画面で確認ボタンをクリックすると、POSTリクエストがTrainingEntryServletへ送信されます。

POST時の流れ

順番内容
1入力画面で確認ボタンをクリックする
2TrainingEntryServletのdoPostメソッドが実行される
3申込ID、氏名、確認コードをリクエストパラメータから取得する
4TrainingEntryインスタンスを作成する
5TrainingEntryインスタンスをセッションスコープに保存する
6trainingEntryConfirm.jspへフォワードする
7確認画面が表示される

ここで重要なのは、入力された申込情報をセッションスコープに保存する点です。

確認画面の表示だけならリクエストスコープでもできそうに見えます。しかし、確認画面から申込実行へ進むときには、別のGETリクエストが送られます。

その次のリクエストでも同じ申込情報を使うため、セッションスコープに保存しておく必要があります。

リクエスト③ 申込を実行する

確認画面で申込リンクをクリックすると、action=doneを付けてTrainingEntryServletへGETリクエストを送ります。

申込実行時の流れ

順番内容
1確認画面で申込をクリックする
2TrainingEntryServletへaction=done付きのGETリクエストを送る
3doGetメソッドが実行される
4actionの値がdoneなので、申込実行と判断する
5セッションスコープからTrainingEntryインスタンスを取得する
6TrainingEntryLogicに申込処理を依頼する
7セッションスコープからTrainingEntryインスタンスを削除する
8trainingEntryDone.jspへフォワードする
9申込完了画面が表示される

このように、入力画面から確認画面、確認画面から完了画面へ進む間に、同じ申込情報を保持するためにセッションスコープを利用します。

リクエストパラメータで処理を振り分ける

このアプリケーションでは、TrainingEntryServletのdoGetメソッドが2つの場面で実行されます。

1つ目は、プログラム開始時に申込入力画面を表示する場面です。

2つ目は、確認画面から申込を実行する場面です。

同じdoGetメソッドでも、場面によって行う処理が異なります。そのため、どこから来たリクエストなのかを判断する必要があります。

そこで、actionというリクエストパラメータを使います。

actionによる処理の振り分け

actionの値判断する内容フォワード先
null申込開始のリクエストWEB-INF/jsp/trainingEntryForm.jsp
done申込実行のリクエストWEB-INF/jsp/trainingEntryDone.jsp

プログラム開始時は、actionを送信しません。そのため、actionの値はnullになります。

確認画面から申込を実行するときは、action=doneを付けてリクエストします。そのため、doGetメソッドでは申込実行のリクエストだと判断できます。

図3:actionパラメータによる処理の振り分け

この図から分かること

同じTrainingEntryServletのdoGetメソッドでも、プログラム開始時と申込実行時では処理が異なります。

そこで、actionというリクエストパラメータを使って、どの場面から呼び出されたのかを判断します。

actionが送られていない場合は、申込開始として入力画面へ進みます。action=doneが送られている場合は、申込実行としてセッションスコープから申込情報を取得し、登録処理を行います。

リクエストとサーブレットクラスの対応

今回のアプリケーションでは、すべてのリクエストをTrainingEntryServletに集めています。

GETリクエストでもPOSTリクエストでも、まずTrainingEntryServletが受け取ります。そのうえで、doGetやdoPostの中で処理を振り分けます。

ただし、必ずこの形にしなければならないわけではありません。

リクエストごとに別々のサーブレットクラスを作る方法もあります。どのリクエストをどのサーブレットで処理するかは、アプリケーションの規模、複雑さ、設計方針によって決めます。

今回の設計

リクエスト実行されるメソッド主な処理
申込開始doGet入力画面へフォワードする
入力内容の確認doPost入力値を取得し、セッションスコープに保存する
申込実行doGetaction=doneで判断し、申込処理を行う

1つのサーブレットに処理を集めると、申込機能全体の流れを1つのクラスで追いやすくなります。

一方で、処理が増えすぎるとサーブレットが長くなりやすいので、機能の規模に応じて設計を考えることが大切です。

JavaBeansを作成する

まず、申込情報を表すJavaBeansを作成します。

TrainingEntry.javaには、申込ID、氏名、確認コードをフィールドとして用意します。

登録する申込情報を表すJavaBeansの例

ファイル名: TrainingEntry.java

package model;

import java.io.Serializable;

public class TrainingEntry implements Serializable {
    private String entryId;
    private String name;
    private String passcode;

    public TrainingEntry() { }

    public TrainingEntry(String entryId, String name, String passcode) {
        this.entryId = entryId;
        this.name = name;
        this.passcode = passcode;
    }

    public String getEntryId() {
        return entryId;
    }

    public String getName() {
        return name;
    }

    public String getPasscode() {
        return passcode;
    }
}

TrainingEntry.javaは、modelパッケージに作成します。

このクラスは、申込に必要な情報を1つのインスタンスとしてまとめる役割を持ちます。

TrainingEntry.javaのポイント

TrainingEntry.javaは、セッションスコープに保存するためのJavaBeansです。

JavaBeansとして確認する点

確認項目内容
パッケージpackage modelでmodelパッケージに所属している
直列化Serializableを実装している
publicなクラスpublic class TrainingEntryとして作成している
引数なしコンストラクタpublic TrainingEntry() { }を用意している
フィールドのカプセル化entryId、name、passcodeをprivateにしている
gettergetEntryId、getName、getPasscodeを用意している

セッションスコープには、関連する情報をまとめたJavaBeansを保存すると扱いやすくなります。

今回は、申込ID、氏名、確認コードをTrainingEntryインスタンスにまとめています。

申込処理を行うモデルを作成する

次に、申込処理を担当するモデルを作成します。

今回は学習用のサンプルなので、実際にファイルやデータベースへ登録する処理は行いません。登録処理を行ったものとしてtrueを返します。

申込処理を行うモデルの例

ファイル名: TrainingEntryLogic.java

package model;

public class TrainingEntryLogic {

    public boolean execute(TrainingEntry entry) {
        // 申込処理
        // 実際のファイル登録やデータベース登録は行わない
        return true;
    }
}

TrainingEntryLogic.javaもmodelパッケージに作成します。

このクラスは、申込処理の担当です。画面表示は行いません。また、リクエストパラメータを直接取得することもありません。

TrainingEntryLogic.javaの役割

TrainingEntryLogic.javaは、登録処理を担当するモデルです。

今回の処理では、TrainingEntryインスタンスを受け取り、申込処理を実行したものとしてtrueを返します。

処理の考え方

処理内容
引数TrainingEntryインスタンスを受け取る
実行内容申込処理を行う
今回のサンプル実際の登録処理は行わずtrueを返す

現段階では、セッションスコープを使った画面遷移とデータ共有の仕組みを理解することが目的です。

そのため、データベースなどへの登録処理は扱わず、登録処理の形だけを確認します。

コントローラを作成する

次に、申込に関するリクエストを処理するサーブレットを作成します。

TrainingEntryServlet.javaは、今回のアプリケーションのコントローラです。

doGetメソッドでは、actionの値によって入力画面を表示するのか、申込処理を実行するのかを判断します。

doPostメソッドでは、入力画面から送信された申込情報を取得し、TrainingEntryインスタンスを作成して、セッションスコープに保存します。

研修コース申込に関するリクエストを処理するコントローラの例

ファイル名: TrainingEntryServlet.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;
import jakarta.servlet.http.HttpSession;
import model.TrainingEntry;
import model.TrainingEntryLogic;

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

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

        // フォワード先
        String forwardPath = null;

        // サーブレットクラスの動作を決定するactionの値を取得
        String action = request.getParameter("action");

        // 申込開始をリクエストされたときの処理
        if (action == null) {
            // フォワード先を設定
            forwardPath = "WEB-INF/jsp/trainingEntryForm.jsp";
        }
        // 確認画面から申込実行をリクエストされたときの処理
        else if (action.equals("done")) {
            // セッションスコープに保存された申込情報を取得
            HttpSession session = request.getSession();
            TrainingEntry entry =
                    (TrainingEntry) session.getAttribute("entryUser");

            // 申込処理の呼び出し
            TrainingEntryLogic logic = new TrainingEntryLogic();
            logic.execute(entry);

            // 不要となったセッションスコープ内のインスタンスを削除
            session.removeAttribute("entryUser");

            // 申込後のフォワード先を設定
            forwardPath = "WEB-INF/jsp/trainingEntryDone.jsp";
        }

        // 設定されたフォワード先にフォワード
        RequestDispatcher dispatcher =
                request.getRequestDispatcher(forwardPath);
        dispatcher.forward(request, response);
    }

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

        // リクエストパラメータの取得
        request.setCharacterEncoding("UTF-8");
        String entryId = request.getParameter("entryId");
        String name = request.getParameter("name");
        String passcode = request.getParameter("passcode");

        // 申込情報を設定
        TrainingEntry entryUser =
                new TrainingEntry(entryId, name, passcode);

        // セッションスコープに申込情報を保存
        HttpSession session = request.getSession();
        session.setAttribute("entryUser", entryUser);

        // フォワード
        RequestDispatcher dispatcher =
                request.getRequestDispatcher(
                        "WEB-INF/jsp/trainingEntryConfirm.jsp");
        dispatcher.forward(request, response);
    }
}

TrainingEntryServlet.javaは、servletパッケージに作成します。

URLパターンは/TrainingEntryServletです。ブラウザからhttp://localhost:8080/study/TrainingEntryServletへアクセスすると、doGetメソッドが実行されます。

doGetメソッドの役割

doGetメソッドは、2つの場面で実行されます。

1つ目は、アプリケーションを開始して入力画面を表示するときです。

2つ目は、確認画面から申込を実行するときです。

この2つを区別するために、actionというリクエストパラメータを使います。

doGetメソッドの分岐

actionの値処理内容
null申込入力画面へフォワードする
doneセッションスコープから申込情報を取得し、申込処理を行う

最初にアクセスしたときは、actionを送信しません。そのため、actionの値はnullになります。

確認画面の申込リンクでは、TrainingEntryServlet?action=doneへアクセスします。そのため、actionの値がdoneになり、申込実行の処理へ進みます。

doPostメソッドの役割

doPostメソッドは、入力画面から確認ボタンをクリックしたときに実行されます。

trainingEntryForm.jspのフォームでは、method属性にpostを指定しています。そのため、確認ボタンをクリックするとPOSTリクエストが送信されます。

doPostメソッドでは、リクエストパラメータから入力値を取得し、TrainingEntryインスタンスを作成します。

doPostメソッドの処理

順番内容
1request.setCharacterEncodingで文字コードを指定する
2entryId、name、passcodeを取得する
3TrainingEntryインスタンスを作成する
4request.getSessionでHttpSessionを取得する
5session.setAttributeでセッションスコープに保存する
6trainingEntryConfirm.jspへフォワードする

ここで作成したTrainingEntryインスタンスは、確認画面でも申込実行時でも使います。

そのため、リクエストスコープではなく、セッションスコープに保存しています。

セッションスコープに保存する処理

TrainingEntryServlet.javaでは、次の流れでセッションスコープに申込情報を保存しています。

まず、入力値をもとにTrainingEntryインスタンスを作成します。

次に、request.getSessionでHttpSessionインスタンスを取得します。

最後に、session.setAttributeでTrainingEntryインスタンスを保存します。

保存処理の対応

処理内容
new TrainingEntry(entryId, name, passcode)申込情報を持つインスタンスを作成する
request.getSessionHttpSessionインスタンスを取得する
session.setAttribute("entryUser", entryUser)entryUserという属性名でセッションスコープに保存する

保存時の属性名はentryUserです。

確認画面や申込実行時には、このentryUserという属性名を使ってセッションスコープからTrainingEntryインスタンスを取得します。

セッションスコープから取得して削除する処理

確認画面から申込を実行すると、TrainingEntryServletのdoGetメソッドが呼ばれます。

このとき、actionの値はdoneです。

doGetメソッドでは、セッションスコープからentryUserを取得し、TrainingEntryLogicに渡して申込処理を行います。

申込処理が終わったら、session.removeAttributeでentryUserを削除します。

取得と削除の対応

処理内容
session.getAttribute("entryUser")セッションスコープから申込情報を取得する
(TrainingEntry)Object型からTrainingEntry型へキャストする
logic.execute(entry)申込処理を実行する
session.removeAttribute("entryUser")不要になった申込情報を削除する

セッションスコープはレスポンス後も情報が残ります。

便利な反面、不要になった情報を残したままにすると、次の処理で古い情報を使ってしまう可能性があります。

今回のように、申込が完了したあとは、保存していた申込情報を削除しておくと安全です。

入力画面を作成する

次に、研修コース申込入力画面を作成します。

trainingEntryForm.jspは、WEB-INF/jspフォルダに作成します。

この画面では、申込ID、確認コード、氏名を入力します。確認コードの入力欄では、inputタグのtype属性にpasswordを指定します。

研修コース申込入力画面を出力するビューの例

ファイル名: trainingEntryForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>研修コース申込</title>
</head>
<body>
<h1>研修コース申込</h1>
<form action="TrainingEntryServlet" method="post">
申込ID:<input type="text" name="entryId"><br>
確認コード:<input type="password" name="passcode"><br>
氏名:<input type="text" name="name"><br>
<input type="submit" value="確認">
</form>
</body>
</html>

このJSPファイルでは、formタグのaction属性にTrainingEntryServletを指定しています。

method属性にはpostを指定しているため、確認ボタンをクリックするとTrainingEntryServletのdoPostメソッドが実行されます。

パスワードボックス

確認コードの入力欄では、inputタグのtype属性にpasswordを指定しています。

type属性の値をpasswordにすると、入力した文字が画面上では伏せ字で表示されます。

password指定の特徴

項目内容
type属性passwordを指定する
表示入力文字が伏せ字で表示される
送信name属性に対応した値として送信される

今回の例では、確認コードの入力欄にname="passcode"を指定しています。

そのため、サーブレット側ではrequest.getParameter("passcode")で取得できます。

入力画面のname属性とサーブレットの対応

trainingEntryForm.jspで指定したname属性は、TrainingEntryServletのdoPostメソッドで値を取得するときに使います。

name属性とgetParameterの対応

JSP側のname属性サーブレット側の取得
entryIdrequest.getParameter("entryId")
namerequest.getParameter("name")
passcoderequest.getParameter("passcode")

name属性とgetParameterの引数が一致していないと、サーブレット側で値を正しく取得できません。

フォームとサーブレットを連携させるときは、name属性とgetParameterの対応を必ず確認しましょう。

確認画面を作成する

次に、申込確認画面を作成します。

trainingEntryConfirm.jspでは、セッションスコープに保存されたTrainingEntryインスタンスを取得し、申込IDと氏名を表示します。

確認コードは、確認画面には表示しません。

研修コース申込確認画面を出力するビューの例

ファイル名: trainingEntryConfirm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<%@ page import="model.TrainingEntry" %>
<%
TrainingEntry entryUser =
        (TrainingEntry) session.getAttribute("entryUser");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>研修コース申込</title>
</head>
<body>
<p>下記の内容で申し込みます</p>
<p>
申込ID:<%= entryUser.getEntryId() %><br>
氏名:<%= entryUser.getName() %><br>
</p>
<a href="TrainingEntryServlet">戻る</a>
<a href="TrainingEntryServlet?action=done">申込</a>
</body>
</html>

このJSPでは、session.getAttribute("entryUser")を使って、セッションスコープからTrainingEntryインスタンスを取得しています。

取得したインスタンスはObject型で返されるため、TrainingEntry型にキャストしています。

確認画面でのセッションスコープ利用

確認画面は、入力内容を利用者に確認してもらうための画面です。

この画面では、TrainingEntryServletのdoPostメソッドでセッションスコープに保存したTrainingEntryインスタンスを取得して表示します。

確認画面で行っていること

処理内容
page import="model.TrainingEntry"JSP内でTrainingEntry型を使えるようにする
session.getAttribute("entryUser")セッションスコープから申込情報を取得する
(TrainingEntry)TrainingEntry型へキャストする
getEntryId申込IDを表示する
getName氏名を表示する

JSPでは暗黙オブジェクトsessionをそのまま使えるため、サーブレットのようにrequest.getSessionを記述する必要はありません。

action=doneを送信するリンク

確認画面の申込リンクでは、次のようにURLの末尾にaction=doneを付けています。

TrainingEntryServlet?action=done

このリンクをクリックすると、TrainingEntryServletへGETリクエストが送られます。

action=doneの役割

指定内容
TrainingEntryServletリクエスト先のサーブレット
?URLとリクエストパラメータを区切る
action=done申込実行であることを表すリクエストパラメータ

TrainingEntryServletのdoGetメソッドでは、request.getParameter("action")でactionの値を取得します。

値がdoneであれば、申込実行のリクエストだと判断します。

完了画面を作成する

最後に、申込完了画面を作成します。

trainingEntryDone.jspでは、申込が完了したことを表示します。

この画面では、すでにTrainingEntryServletで申込処理が行われ、セッションスコープから申込情報も削除されています。

研修コース申込完了画面を出力するビューの例

ファイル名: trainingEntryDone.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>研修コース申込</title>
</head>
<body>
<p>申込が完了しました</p>
<a href="TrainingEntryServlet">戻る</a>
</body>
</html>

完了画面には、申込が完了したことを知らせるメッセージを表示します。

戻るリンクをクリックすると、TrainingEntryServletへGETリクエストが送られます。このときactionは送信されないため、入力画面へ戻ります。

実行方法

6つのファイルを作成したら、TrainingEntryServletを実行して動作を確認します。

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

http://localhost:8080/study/TrainingEntryServlet

または、EclipseでTrainingEntryServlet.javaを選択し、サーバーで実行します。

実行の流れ

操作表示される画面
TrainingEntryServletへアクセスする研修コース申込入力画面
申込ID、確認コード、氏名を入力して確認をクリックする研修コース申込確認画面
申込をクリックする研修コース申込完了画面
戻るをクリックする研修コース申込入力画面

動作確認では、最初にTrainingEntryServletへアクセスすることが大切です。

WEB-INF内にあるJSPファイルは、ブラウザから直接リクエストできません。必ずサーブレットからフォワードして表示します。

セッションスコープを使うプログラム実行時の注意点

セッションスコープを使うプログラムでは、以前に保存したインスタンスが残っていることがあります。

そのため、開発途中で何度も実行していると、コードが正しくても、思ったような結果にならない場合があります。

そのようなときは、開いているブラウザをすべて閉じてから、もう一度実行してみましょう。

実行結果がおかしいときの確認

状況対応
以前の入力内容が残っているように見えるブラウザをすべて閉じて実行し直す
完了後も古い情報が使われるremoveAttributeで削除しているか確認する
確認画面で情報が表示されないsession.setAttributeの属性名とsession.getAttributeの属性名を確認する
最初の画面が出ないactionの値による分岐を確認する

セッションスコープはリクエストをまたいでインスタンスを保持できるため便利です。

ただし、開発中は前回の情報が残っていることもあるため、動作確認ではセッションの状態を意識することが大切です。

セッションスコープを使う理由

今回のアプリケーションでセッションスコープを使う理由は、確認画面から申込実行へ進むときに、入力された申込情報を再利用する必要があるからです。

入力画面から確認画面へ進むだけであれば、リクエストスコープでも情報を渡せます。

しかし、確認画面から申込をクリックすると、新しいGETリクエストが発生します。リクエストスコープは前回のレスポンスが返った時点で消えているため、この新しいリクエストでは前回の申込情報を取得できません。

リクエストスコープでは困る点

場面リクエストスコープの場合
入力画面から確認画面へフォワード中なら利用できる
確認画面から申込実行へ新しいリクエストなので利用できない
申込処理で入力内容を使う前回の情報を取得できない

セッションスコープに保存しておけば、確認画面を表示したあとでも、申込実行時に同じTrainingEntryインスタンスを取得できます。

ブラウザの表示例:入力画面

ブラウザの表示例:確認画面

ブラウザの表示例:申込完了画面

完了後にセッションスコープから削除する理由

セッションスコープは、リクエストをまたいでデータを保持できます。

しかし、不要になったデータまで残し続けると、次の処理で古い情報を使ってしまう可能性があります。

今回のアプリケーションでは、申込処理が完了したあと、entryUserをセッションスコープから削除しています。

削除する理由

理由内容
古い申込情報を残さない次回の申込で前回の情報を使わないようにする
不要なインスタンスを整理するセッションスコープに余計な情報を残さない
処理の区切りを明確にする申込完了後は申込情報を使い終わったことを示す

セッションスコープは便利ですが、保存したインスタンスをいつ削除するかも重要です。

今回のように、確認画面と申込実行で使い終わった情報は、完了処理の中でremoveAttributeを使って削除します。

確認したいポイント

セッションスコープを使ったWebアプリケーションでは、ファイル同士のつながりを確認しながら作成することが大切です。

動作確認のポイント

確認項目内容
URLパターン@WebServlet("/TrainingEntryServlet")になっているか
実行URLhttp://localhost:8080/study/TrainingEntryServletになっているか
JSPの保存場所WEB-INF/jspに配置しているか
入力画面のaction属性TrainingEntryServletになっているか
入力画面のmethod属性postになっているか
name属性entryId、name、passcodeがdoPostの取得名と一致しているか
セッション保存session.setAttribute("entryUser", entryUser)で保存しているか
セッション取得session.getAttribute("entryUser")で取得しているか
申込リンクTrainingEntryServlet?action=doneになっているか
action分岐nullとdoneで処理を分けているか
セッション削除申込完了後にremoveAttributeで削除しているか

セッションスコープを使うと、複数の画面をまたいで同じインスタンスを扱えるようになります。

入力、確認、完了のような画面遷移では、どのタイミングで保存し、どのタイミングで取得し、どのタイミングで削除するのかを意識すると、処理の流れがつかみやすくなります。