はじめに (対象読者・この記事でわかること)
この記事は、JavaサーブレットやJSPを使ってWebアプリケーションを開発している初心者〜中級者を対象としています。特に、入力フォーム送信後にエラーメッセージを表示したり、確認画面に戻したりしたいときに、ユーザーが入力した値を保持できずに困った経験がある方に向けた内容です。本記事を読むと、リクエストパラメータの取得方法から、リクエストスコープ、セッションスコープ、そしてEL(Expression Language)やJSTLを組み合わせた実装パターンまで、実際のコード例とともに理解でき、フォームの値保持をスムーズに実装できるようになります。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Javaの基本文法とオブジェクト指向概念
- HTML/CSSの基本的な知識
- サーブレット/JSPの概要(Web.xml の設定やディレクトリ構成)
JSPで入力値を保持する必要性と基本概念
Webアプリケーションにおいて、ユーザーが入力した情報を「次の画面でも使える」ように保持するケースは多くあります。代表的なシーンとしては、バリデーションエラー時に入力内容を再表示したり、確認画面で入力内容を一時的に保持したりする場合です。
JSP だけで完結させると、request.getParameter() で取得できるのは直前の HTTP リクエストだけです。したがって、ページ遷移が発生したときに値が失われる ことがあります。この問題を解決するために、以下の 3 つのスコープが利用されます。
| スコープ | 期間 | 主な用途 |
|---|---|---|
| リクエストスコープ | 1 回のリクエスト/レスポンスサイクル | バリデーションエラー時の再表示や、同一リクエスト内でのデータ受け渡し |
| セッションスコープ | ユーザーがブラウザを閉じるか、セッションが破棄されるまで | ログイン情報や、複数ページにわたる入力情報の保持 |
| アプリケーションスコープ | サーバーが起動している間 | アプリ全体で共有する設定情報やキャッシュ |
本記事では、リクエストスコープ と セッションスコープ を中心に、EL と JSTL を併用した実装方法を解説します。まずは最もシンプルなリクエストスコープでの保持方法を学び、次にセッションスコープへ拡張する流れです。
具体的な実装ステップとコード例
ステップ1:入力フォームの作成
まずは HTML でシンプルな入力フォームを用意します。action は受信サーブレットに向け、method は POST を使用します。
Html<!-- /WEB-INF/jsp/inputForm.jsp --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>ユーザー情報入力</title> </head> <body> <h2>ユーザー情報入力</h2> <form action="${pageContext.request.contextPath}/confirm" method="post"> <label>名前: <input type="text" name="name" value="${param.name}" /></label><br/> <label>年齢: <input type="number" name="age" value="${param.age}" /></label><br/> <input type="submit" value="確認画面へ"/> </form> <c:if test="${not empty errorMessage}"> <p style="color:red;">${errorMessage}</p> </c:if> </body> </html>
ポイントは次の通りです。
value="${param.name}"で リクエストパラメータ が存在すれば自動的に再表示。バリデーションエラー時に有効。- JSTL の
<c:if>を使ってエラーメッセージを条件表示。
ステップ2:受信サーブレットでパラメータ取得とスコープ設定
次に、フォーム送信先のサーブレット ConfirmServlet を実装します。ここではリクエストパラメータを取得し、簡易バリデーションを行い、エラーがなければ リクエストスコープ に保持して確認画面へフォワード、エラーがあれば再び入力画面へリダイレクトします。
Java// src/main/java/com/example/servlet/ConfirmServlet.java package com.example.servlet; import jakarta.servlet.*; import jakarta.servlet.http.*; import jakarta.servlet.annotation.*; import java.io.IOException; @WebServlet("/confirm") public class ConfirmServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String ageStr = request.getParameter("age"); String errorMessage = null; // 簡易バリデーション if (name == null || name.isBlank()) { errorMessage = "名前は必須です。"; } else if (ageStr == null || ageStr.isBlank()) { errorMessage = "年齢は必須です。"; } if (errorMessage != null) { // エラーがあれば入力画面へ戻す request.setAttribute("errorMessage", errorMessage); // 入力内容は param で保持されているのでそのまま転送 RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/inputForm.jsp"); rd.forward(request, response); return; } // 正常時はリクエストスコープに保持して確認画面へ request.setAttribute("name", name); request.setAttribute("age", ageStr); RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/jsp/confirm.jsp"); rd.forward(request, response); } }
request.setAttribute()で リクエストスコープ にデータを格納。- バリデーションエラー時は
request.setAttribute("errorMessage", …)して同じ JSP にフォワードさせ、入力値は自動的に${param.xxx}で復元されます。
ステップ3:確認画面 JSP での表示
保持したデータを EL で取得し、ユーザーに確認させる画面です。
Jsp<!-- /WEB-INF/jsp/confirm.jsp --> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>入力内容確認</title> </head> <body> <h2>入力内容の確認</h2> <p>名前: ${name}</p> <p>年齢: ${age}</p> <form action="${pageContext.request.contextPath}/register" method="post"> <!-- 確認画面でもデータを送る必要がある場合は hidden で保持 --> <input type="hidden" name="name" value="${name}" /> <input type="hidden" name="age" value="${age}" /> <input type="submit" value="登録"/> </form> <a href="${pageContext.request.contextPath}/input">修正する</a> </body> </html>
ポイント
- request スコープに入っている属性は ${name} のように EL だけで取得可能。
- 次のステップ(実際の登録処理)へ渡す場合は、hidden フィールドで値を引き継ぎます。
ステップ4:セッションスコープでの永続的保持(任意)
確認画面から「戻る」ボタンで入力画面に遷移した際に、リクエストスコープは失われます。セッションスコープを利用すれば、ユーザーがページ間を行き来しても入力内容を保持できます。
Java// ConfirmServlet の一部修正例 if (errorMessage == null) { // セッションに保存 HttpSession session = request.getSession(); session.setAttribute("tempName", name); session.setAttribute("tempAge", ageStr); // 確認画面へフォワード request.setAttribute("name", name); request.setAttribute("age", ageStr); // ... }
確認画面 JSP では ${sessionScope.tempName} とすれば取得可能です。また、最終的に登録が完了したら session.removeAttribute(...) でクリアします。
ハマった点やエラー解決
| 発生した問題 | 原因 | 解決策 |
|---|---|---|
| 確認画面に遷移した直後、入力値が表示されない | バリデーションエラー時に request.setAttribute ではなく request.setParameter を使用していた |
request.setAttribute に統一し、JSP 側は ${param.xxx} で取得するように変更 |
| セッションに保存したデータが別ユーザーにも見える | session を request.getSession(false) で取得し、false が返ったときに新規作成していなかった |
request.getSession(true)(デフォルト)で常にユーザー固有のセッションを取得 |
| JSP が文字化けする | request.setCharacterEncoding("UTF-8") をサーブレットで設定していなかった |
すべてのサーブレットの doPost で setCharacterEncoding("UTF-8") を呼び出す |
| JSTL タグが動作しない | web.xml に JSTL へ必要な URI が未登録 |
web.xml に <jsp-config><taglib></taglib></jsp-config> を追加、もしくは JSP のページ指示子で taglib を明示 |
解決策のまとめ
- リクエストスコープ は同一リクエスト内で完結する簡易保持に適しています。
- セッションスコープ はページ間を跨いだ永続的な保持が必要なときに利用しますが、不要なデータは必ず削除してメモリリークを防止します。
- EL と JSTL を併用すると、Java コードを書かずにビュー側で条件分岐や表示ロジックを実装でき、保守性が向上します。
まとめ
本記事では、JSP における「入力フォームの値保持」について、リクエストスコープ と セッションスコープ の使い分け、EL/JSTL を活用した表示方法、そして実装時に遭遇しやすいエラーとその対処法を具体的なコード例とともに解説しました。
- 入力値は
request.setAttributeでリクエストスコープに保持し、EL で簡潔に取得できる。 - バリデーションエラー時はパラメータを
${param.xxx}で再表示し、ユーザー体験を損なわない。 - 複数画面に跨がる場合はセッションスコープを利用し、不要になったら必ず削除する。
この手順をマスターすれば、ユーザーが入力した情報を安全かつ柔軟に保持でき、エラー処理や確認画面の実装が格段に楽になります。次回は、CSRF 対策や AJAX を組み合わせた非同期バリデーションについても取り上げる予定です。
参考資料
- Jakarta EE 公式ドキュメント – Servlet & JSP
- JSTL 公式リファレンス
- 「サーブレット&JSP プログラミング」(著: 山田祥寛, 技術評論社)
- Spring MVC でのフォームバリデーション解説記事
