サーブレット/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メソッドに以下の記述をします。
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ファイルを新規作成して以下のようにフォームの記述をします。
<%@ 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メソッドを記述して、リクエストパラメータを受け取ります。
@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");
}
入力チェックをする
サーブレットから引数を受け取って、入力内容をチェック、問題があればエラーメッセージを追加するクラスを作成します。
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メソッドから以下のような記述で引数を渡します。
import model.CheckRegistrationForm;
@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の仕様に基づいて、データベースのテーブルをそのまま抽出したクラス)が必要なので別途作成します。
import bean.MemberBean;
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メソッドに記述します。
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ファイルも必要なので、作成します。
<%@ 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ファイルに、エラーメッセージのインスタンスを受け取って表示する記述を追加します。
<body>
<main>
<p class="red">${errorMessage}</p>
<!-- 以下省略 -->
</main>
</body>
(この際、EL式にしないと最初に入力画面を表示した際にnullが表示されてしまいます。)
Eclipseから実行してみる
Eclipseで制作した場合は、サーブレットを右クリック→「実行」からTomCatで実行します。
入力確認画面に遷移、またはエラーメッセージが表示されればOKです。
次回の学習に向けて
まず、バックエンドに関しては詳細なバリデーションの実装とJDBCを使ったデータベースとの連携を学んで、より実用的なフォームを目指します。
フロントエンドに関しては、CSSによる綺麗で使いやすいレイアウトを目指します。