はじめに (対象読者・この記事でわかること)

この記事は、JavaでWebアプリケーション開発を行っている方、特にServletとJSPの基礎知識がある方を対象としています。この記事を読むことで、ユーザーからのフォーム入力に基づいて動的に画面遷移先を変更する実装方法が理解できます。具体的には、ユーザーが選択したボタンや入力した内容に応じて、遷移先のJSPページを切り替えるロジックを構築する方法を学べます。また、実際のコード例を通じて、実践的なスキルを習得できます。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 - Javaの基本的な文法とオブジェクト指向の理解 - ServletとJSPの基本的な知識 - HTMLフォームの基本的な理解 - MavenやGradleなどのビルドツールの基本的な操作

動的画面遷移の概要と必要性

Webアプリケーション開発において、ユーザーからの入力に応じて画面遷移先を動的に変更する機能は非常に重要です。例えば、ユーザーがログインフォームで管理者としてログインした場合と一般ユーザーとしてログインした場合で遷移先を変更する、といったシナリオが考えられます。静的な遷移では対応できない複雑なビジネスロジックを実装するために、動的画面遷移の技術は必須です。

JavaのWeb開発では、ServletとJSPを組み合わせてこのような機能を実現します。リクエストパラメータやセッション属性を参照し、条件分岐によって遷移先を決定します。この記事では、具体的な実装方法とベストプラクティスを解説します。

具体的な実装方法

ステップ1:プロジェクトのセットアップ

まず、Mavenを使用したJava Webプロジェクトをセットアップします。pom.xmlには以下の依存関係を追加します。

Xml
<dependencies> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- JSP API --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- JSTL --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies>

ステップ2:フォームページの作成

次に、ユーザーからの入力を受け付けるフォームページを作成します。ここでは、ユーザーが役割(管理者または一般ユーザー)を選択できるようにします。

index.jsp:

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="login" method="post"> <div> <label for="username">ユーザー名:</label> <input type="text" id="username" name="username" required> </div> <div> <label for="password">パスワード:</label> <input type="password" id="password" name="password" required> </div> <div> <label for="role">役割:</label> <select id="role" name="role"> <option value="admin">管理者</option> <option value="user">一般ユーザー</option> </select> </div> <div> <button type="submit">ログイン</button> </div> </form> </body> </html>

ステップ3:Servletの作成

次に、フォームから送信されたデータを受け取り、役割に応じて遷移先を変更するServletを作成します。

LoginServlet.java:

Java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/login") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // リクエストパラメータの取得 String username = request.getParameter("username"); String password = request.getParameter("password"); String role = request.getParameter("role"); // 簡単なバリデーション(実際のアプリケーションではより厳密な検証が必要) if (username == null || username.isEmpty() || password == null || password.isEmpty()) { request.setAttribute("errorMessage", "ユーザー名とパスワードを入力してください"); request.getRequestDispatcher("/index.jsp").forward(request, response); return; } // ロールに基づいて遷移先を決定 String forwardPath; if ("admin".equals(role)) { forwardPath = "/admin/dashboard.jsp"; } else { forwardPath = "/user/dashboard.jsp"; } // ユーザー情報をリクエストスコープに設定 request.setAttribute("username", username); request.setAttribute("role", role); // 遷移先にフォワード request.getRequestDispatcher(forwardPath).forward(request, response); } }

ステップ4:遷移先ページの作成

役割に応じて遷移する先のページを作成します。

admin/dashboard.jsp:

Jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>管理者ダッシュボード</title> </head> <body> <h1>管理者ダッシュボード</h1> <p>ようこそ、${username}さん(管理者)</p> <p>管理者専用のコンテンツが表示されています。</p> <ul> <li>ユーザー管理</li> <li>システム設定</li> <li>ログ確認</li> </ul> <a href="logout">ログアウト</a> </body> </html>

user/dashboard.jsp:

Jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ユーザーダッシュボード</title> </head> <body> <h1>ユーザーダッシュボード</h1> <p>ようこそ、${username}さん</p> <p>一般ユーザー向けのコンテンツが表示されています。</p> <ul> <li>プロフィール編集</li> <li>設定変更</li> <li>お問い合わせ</li> </ul> <a href="logout">ログアウト</a> </body> </html>

ステップ5:リダイレクトを使用した遷移

フォワードの代わりにリダイレクトを使用する場合の実装例です。リダイレクトはクライアント側で新しいリクエストが発生するため、URLが変更されます。

LoginServlet.javaの修正版(リダイレクトを使用):

Java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/login") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // リクエストパラメータの取得 String username = request.getParameter("username"); String password = request.getParameter("password"); String role = request.getParameter("role"); // 簡単なバリデーション if (username == null || username.isEmpty() || password == null || password.isEmpty()) { response.sendRedirect("index.jsp?error=1"); return; } // ロールに基づいて遷移先を決定 String redirectPath; if ("admin".equals(role)) { redirectPath = "admin/dashboard?username=" + username; } else { redirectPath = "user/dashboard?username=" + username; } // リダイレクト response.sendRedirect(redirectPath); } }

ステップ6:セッションを使用した状態管理

より複雑なアプリケーションでは、セッションを使用してユーザーの状態を管理することが一般的です。

LoginServlet.javaのセッションを使用した修正版:

Java
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet("/login") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // リクエストパラメータの取得 String username = request.getParameter("username"); String password = request.getParameter("password"); String role = request.getParameter("role"); // 簡単なバリデーション if (username == null || username.isEmpty() || password == null || password.isEmpty()) { request.setAttribute("errorMessage", "ユーザー名とパスワードを入力してください"); request.getRequestDispatcher("/index.jsp").forward(request, response); return; } // セッションの取得 HttpSession session = request.getSession(); // ユーザー情報をセッションに設定 session.setAttribute("username", username); session.setAttribute("role", role); // ロールに基づいて遷移先を決定 String forwardPath; if ("admin".equals(role)) { forwardPath = "/admin/dashboard.jsp"; } else { forwardPath = "/user/dashboard.jsp"; } // 遷移先にフォワード request.getRequestDispatcher(forwardPath).forward(request, response); } // ログアウト処理 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } response.sendRedirect("index.jsp"); } }

ハマった点やエラー解決

問題1:文字化けの発生

日本語の入力を受け付けるフォームで文字化けが発生する場合があります。

解決策

Webアプリケーションの文字エンコーディングを正しく設定する必要があります。web.xmlにフィルタを追加して、リクエストとレスポンスの文字エンコーディングを設定します。

web.xml:

Xml
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

問題2:セッションタイムアウト

セッションを使用していると、一定時間操作がないとセッションがタイムアウトしてしまいます。

解決策

セッションのタイムアウト時間を設定するか、アクティビティがあるたびにセッションの有効期限を延長します。

web.xmlでセッションタイムアウトを設定:

Xml
<session-config> <session-timeout>30</session-timeout> </session-config>

アクティビティがあるたびにセッションの有効期限を延長するコード例:

Java
HttpSession session = request.getSession(); session.setAttribute("username", username); // 既存のセッション属性を更新

問題3:CSRF対策

セッションを使用した認証を行うと、CSRF(クロスサイトリクエストフォージェリ)攻撃の対象となります。

解決策

CSRFトークンを使用して、リクエストが正当なものかを検証します。

LoginFormTag.java (カスタムタグ):

Java
import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.SimpleTagSupport; import java.io.IOException; import java.util.UUID; public class LoginFormTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { // セッションにCSRFトークンを保存 String token = UUID.randomUUID().toString(); getJspContext().getSession().setAttribute("csrfToken", token); // トークンを含むフォームを生成 getJspContext().getOut().println("<input type=\"hidden\" name=\"csrfToken\" value=\"" + token + "\">"); } }

index.jspでカスタムタグを使用:

Jsp
<%@ taglib prefix="my" uri="/WEB-INF/tags/mytags" %> ... <form action="login" method="post"> ... <my:csrfToken/> <button type="submit">ログイン</button> </form>

LoginServlet.javaでCSRFトークンを検証:

Java
// CSRFトークンの検証 String sessionToken = (String) request.getSession().getAttribute("csrfToken"); String requestToken = request.getParameter("csrfToken"); if (sessionToken == null || !sessionToken.equals(requestToken)) { request.setAttribute("errorMessage", "不正なリクエストです"); request.getRequestDispatcher("/index.jsp").forward(request, response); return; }

まとめ

本記事では、Javaを使用してフォーム入力に基づく動的画面遷移を実装する方法を解説しました。

  • フォームから送信されたデータを受け取り、条件分岐で遷移先を変更する方法
  • フォワードとリダイレクトの違いと使い分け
  • セッションを使用した状態管理の実装
  • 文字化け対策、セッションタイムアウト、CSRF対策などの実践的な課題解決

この記事を通して、Java Webアプリケーションにおける動的画面遷移の実装方法を理解し、実践的なスキルを習得できたことと思います。今後は、より複雑なビジネスロジックを組み合わせた画面遷移や、Spring Frameworkを使用した実装方法についても記事にする予定です。

参考資料