0
0

【サーブレット/JSP】フォームとエラーメッセージの表示を覚える

Last updated at Posted at 2024-07-18

サーブレット/JSPで、フォームの表示と、入力に対してのエラーメッセージを表示する方法を覚えるための自分用メモです。

使用環境

PC:MacBook Air 2018
OS:macOS Sonoma 14.3.1
IDE:Eclipse 2023
Webコンテナ:Tomcat 10.1.18

フォームとは?

フォームとは、HTMLのformタグで記述してWebページに表示できる、入力欄や送信ボタンです。
サーブレット/JSPでは、JSPでフォームを表示してサーブレットに入力データを送ることで、データの処理やJSPでの結果の表示が行えます。

フォーム(JSPファイル)を表示するサーブレットを作成する

まず、フォームを記述したJSPファイル(registrationForm.jsp)を表示するために、サーブレットのdoGetメソッドに以下の記述をします。

RegistrationFormServlet.java
package servlet;

import java.io.IOException;

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

public class RegistrationFormServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // JSPファイルを指定してフォワード
        RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/registrationForm.jsp");
        dispatcher.forward(request, response);
    }

}

JSPファイルにフォームの記述をする

次に、JSPファイルを新規作成して以下のようにフォームの記述をします。

registrationForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>会員登録</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header id="header">
        <div class="flex-item wrapper">
            <h1><a href="IndexServlet">SampleSite</a></h1>
        </div>
    </header>
    <main>
        <section id="registration-form">
            <h2>会員登録</h2>
            <form action="RegistrationFormServlet" method="post">
                <div class="row">
                    <label for="name" class="label-title">名前</label>
                    <input type="text" name="name" id="name" class="text-box">
                </div>
                <div class="row">
                    <label for="gender" class="label-title">性別</label>
                    <div>
                        <input type="checkbox" name="gender" id="man" value="男性">
                        <label for="man">男性</label>
                    </div>
                    <div>
                        <input type="checkbox" name="gender" id="woman" value="女性">
                        <label for="woman">女性</label>
                    </div>
                    <div>
                        <input type="checkbox" name="gender" id="none" value="選択しない">
                        <label for="none">選択しない</label>
                    </div>
                </div>
                <div class="row">
                    <label class="label-title">生年月日</label>
                    <div>
                        <select name="year" id="year">
                            <option value="">選択してください</option>
                            <option value="1900">1900</option>
                            <!-- 以下省略 -->
                        </select>
                        <label for="year"></label>
                    </div>
                    <div>
                        <select name="month" id="month">
                            <option value="">選択してください</option>
                            <option value="1">1</option>
                            <!-- 以下省略 -->
                        </select>
                        <label for="month"></label>
                    </div>
                    <div>
                        <select name="day">
                            <option value="">選択してください</option>
                            <option value="1">1</option>
                            <!-- 以下省略 -->
                        </select>
                        <label for="day"></label>
                    </div>
                </div>
                <div class="row">
                    <label for="email" class="label-title">メールアドレス</label>
                    <input type="email" name="email" id="email" class="text-box">
                </div>
                <div class="row">
                    <label for="password" class="label-title">パスワード</label>
                    <input type="password" name="password" id="password" class="text-box">
                </div>
                <input type="submit" value="登録">
            </form>
        </section>
    </main>
</body>
</html>

今回は、名前、性別、生年月日、メールアドレス、パスワードといった簡単なアカウント情報を入力(登録)するフォームにしました。

送信ボタンを押すと、入力した情報(リクエストパラメータ)の送信先(サーブレットクラス)とリクエストメソッド(doGet or doPost)が指定され、アプリケーションサーバーに格納されます。

サーブレットクラスのdoPostメソッドでリクエストパラメータを受け取る

サーブレットクラスにdoPostメソッドを記述して、リクエストパラメータを受け取ります。

RegistrationFormServlet.java
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 文字コードを指定してリクエストパラメータを受け取る
        request.setCharacterEncoding("UTF-8");
        String name = request.getParameter("name");
        String gender = request.getParameter("gender");
        String year = request.getParameter("year");
        String month = request.getParameter("month");
        String day = request.getParameter("day");
        String email = request.getParameter("email");
        String password = request.getParameter("password");
    }

入力チェックをする

サーブレットから引数を受け取って、入力内容をチェック、問題があればエラーメッセージを追加するクラスを作成します。

CheckRegistrationForm.java
package model;

public class CheckRegistrationForm {
	private String errorMessage;
	
	public CheckRegistrationForm() {
		errorMessage = ""; // エラーメッセージ文頭のnullを消すため
	}
	
	public String checkAll(String name, String gender, String year, String month, String day, String email, String password) {
		checkName(name);
		checkGender(gender);
		checkYear(year);
		checkMonth(month);
		checkDay(day);
		checkEmail(email);
		checkPassword(password);
		return errorMessage;
	}
    // 文字列を受け取って空かどうか判定するメソッド
    private void checkNull(String target, String targetName) {
        if(target == null || target.isEmpty()) {
            errorMessage += targetName + "が入力されていません。<br>";
        }
    }
	private void checkName(String name) {
        checkNull(name, "名前");
		// 以下チェック条件省略
	}
	private void checkGender(String gender) {
        checkNull(gender, "性別");
		// 以下チェック条件省略
	}
	private void checkYear(String year) {
        checkNull(year, "生年月日(年)");
		// 以下チェック条件省略
	}
	private void checkMonth(String month) {
        checkNull(month, "生年月日(月)");
		// 以下チェック条件省略
	}
	private void checkDay(String day) {
        checkNull(day, "生年月日(日)");
		// 以下チェック条件省略
	}
	private void checkEmail(String email) {
        checkNull(email, "メールアドレス");
		// 以下チェック条件省略
	}
	private void checkPassword(String password) {
        checkNull(password, "パスワード");
		// 以下チェック条件省略
	}
}

今回は、未入力に対するチェック条件のみ記述しました。
作成したら、サーブレットのdoPostメソッドから以下のような記述で引数を渡します。

RegistrationFormServlet.java
import model.CheckRegistrationForm;
RegistrationFormServlet.java
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 文字コードを指定してリクエストパラメータを受け取る
        request.setCharacterEncoding("UTF-8");
        String name = request.getParameter("name");
        String gender = request.getParameter("gender");
        String year = request.getParameter("year");
        String month = request.getParameter("month");
        String day = request.getParameter("day");
        String email = request.getParameter("email");
        String password = request.getParameter("password");
        
        // リクエストパラメータの値を引数で渡してエラーメッセージを受け取る
        CheckRegistrationForm checkRegistrationForm = new CheckRegistrationForm();
        String errorMessage = checkRegistrationForm.checkAll(name, gender, year, month, day, email, password);
    }

入力確認画面を表示、または入力画面を再度表示する

入力内容をセッションスコープに保存するため、Entity(JavaBeansの仕様に基づいて、データベースのテーブルをそのまま抽出したクラス)が必要なので別途作成します。

RegistrationFormServlet.java
import bean.MemberBean;
MemberBean.java
package bean;

import java.io.Serializable;

public class MemberBean implements Serializable {
    private String id;
	private String name;
	private String gender;
	private String year;
	private String month;
	private String day;
	private String email;
	private String password;
	
	public MemberBean() {
	}
    public MemberBean(String id, String name, String gender, String year, String month, String day, String email, String password) {
        this.id = id;
		this.name = name;
		this.gender = gender;
		this.year = year;
		this.month = month;
		this.day = day;
		this.email = email;
		this.password = password;
	}
	public MemberBean(String name, String gender, String year, String month, String day, String email, String password) {
		this.name = name;
		this.gender = gender;
		this.year = year;
		this.month = month;
		this.day = day;
		this.email = email;
		this.password = password;
	}

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	public String getYear() {
		return year;
	}
	public void setYear(String year) {
		this.year = year;
	}
	public String getMonth() {
		return month;
	}
	public void setMonth(String month) {
		this.month = month;
	}
	public String getDay() {
		return day;
	}
	public void setDay(String day) {
		this.day = day;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPasword(String password) {
		this.password = password;
	}
}

次に、エラーメッセージがなければ入力確認画面、エラーメッセージがあれば入力画面を再度表示するif文をサーブレットのdoPostメソッドに記述します。

RegistrationFormServlet.java
        if(errorMessage.isEmpty()) {
        	// セッションスコープにBeanのインスタンスを保存する
        	MemberBean memberBean = new MemberBean(name, gender, year, month, day, email, password);
        	HttpSession session = request.getSession();
        	session.setAttribute("memberBean", memberBean);
            
            // JSPファイルを指定してフォワード
            RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/confirmRegistrationForm.jsp");
            dispatcher.forward(request, response);
        } else {
        	// リクエストスコープにエラーメッセージのインスタンスを保存する
        	request.setAttribute("errorMessage", errorMessage);
            
            // JSPファイルを指定してフォワード
        	RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/registrationForm.jsp");
            dispatcher.forward(request, response);
        }

また、Entityのインスタンスを受け取って、入力内容を表示するJSPファイルも必要なので、作成します。

confirmRegistrationForm.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="bean.MemberBean" %>
<%
MemberBean memberBean = (MemberBean)session.getAttribute("memberBean");
%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>入力内容確認</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header id="header">
        <div class="flex-item wrapper">
            <h1><a href="IndexServlet">SampleSite</a></h1>
        </div>
    </header>
    <main>
        <section id="confirm-registration">
            <h2>入力内容確認</h2>
            <p>入力内容を確認の上、登録ボタンをクリックしてください。</p>
            <div class="row">
                <h3>名前</h3>
                <p><%= memberBean.getName() %></p>
            </div>
            <div class="row">
                <h3>性別</h3>
                <p><%= memberBean.getGender() %></p>
            </div>
            <div class="row">
                <h3>生年月日</h3>
                <p><%= memberBean.getYear() %><%= memberBean.getMonth() %><%= memberBean.getDay() %></p>
            </div>
            <div class="row">
                <h3>メールアドレス</h3>
                <p><%= memberBean.getEmail() %></p>
            </div>
            <div class="row">
                <h3>パスワード</h3>
                <p><%= memberBean.getPassword() %></p>
            </div>
            <div class="flex-button">
                <div class="white-button"><a href="RegistrationFormServlet">戻る</a></div>
                <div class="black-button"><a href="">登録</a></div>
            </div>
        </section>
    </main>
</body>
</html>

最後に、入力画面のJSPファイルに、エラーメッセージのインスタンスを受け取って表示する記述を追加します。

registrationForm.jsp
<body>
    <main>
        <p class="red">${errorMessage}</p>
        <!-- 以下省略 -->
    </main>
</body>

(この際、EL式にしないと最初に入力画面を表示した際にnullが表示されてしまいます。)

Eclipseから実行してみる

Eclipseで制作した場合は、サーブレットを右クリック→「実行」からTomCatで実行します。
入力確認画面に遷移、またはエラーメッセージが表示されればOKです。
member_2.jpg
member_3.jpg
member_4.jpg

次回の学習に向けて

まず、バックエンドに関しては詳細なバリデーションの実装とJDBCを使ったデータベースとの連携を学んで、より実用的なフォームを目指します。
フロントエンドに関しては、CSSによる綺麗で使いやすいレイアウトを目指します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0