ユーザー登録機能の実装手順
前提: 「JSP/Servlet 環境設定手順書」のセクション3まで完了していること
全体の流れ
| ステップ | 学ぶこと | 作成・変更するファイル |
|---|---|---|
| 1 | サーブレットからINSERTする方法 |
UserDao.java, InsertServlet.java, web.xml
|
| 2 | フォームの値をサーブレットで受け取る方法 |
form.jsp, FormServlet.java, web.xml
|
| 3 | フォーム入力をDBに登録する方法 |
FormServlet.java を修正 |
| 4 | 成功・失敗で画面を切り替える方法 |
success.jsp, FormServlet.java を修正 |
全体像: 各ステップで何が増えるか
ステップ 1: サーブレットからデータを追加する
目的
URLにアクセスするだけで、サーブレットがデータベースに1件INSERTする仕組みを作る。
まだフォームは使わず、Javaコードからデータを登録する流れを理解する。
1-1. UserDao に insert メソッドを追加
UserDao.java を開き、getById() メソッドの下に以下のメソッドを追加する。
/**
* ユーザーを1件データベースに登録する。
*
* getById() との違い:
* getById() → SELECT(読み取り)→ executeQuery() → ResultSet が返る
* insert() → INSERT(書き込み)→ executeUpdate() → 処理件数(int) が返る
*
* @param user 登録するユーザー情報(email, name, password を設定済みであること)
* @return 登録成功なら true、失敗(email重複など)なら false
*/
public boolean insert(User user) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(URL, USER, PASS);
// INSERT文を準備(? はプレースホルダー)
// user_id は AUTO_INCREMENT なので指定しない → DBが自動採番
PreparedStatement ps = conn.prepareStatement(
"INSERT INTO users (email, name, password) VALUES (?, ?, ?)");
// ? に値をセット(1番目 = email, 2番目 = name, 3番目 = password)
ps.setString(1, user.getEmail());
ps.setString(2, user.getName());
ps.setString(3, user.getPassword());
// INSERT/UPDATE/DELETE は executeUpdate() を使う(executeQuery() は SELECT 用)
// 戻り値は「何件処理したか」(INSERT 1件なら 1 が返る)
int count = ps.executeUpdate();
return count > 0;
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
return false;
}
}
getById() と insert() の比較:
| getById()(SELECT) | insert()(INSERT) | |
|---|---|---|
| SQL実行メソッド | executeQuery() |
executeUpdate() |
| 戻り値 |
ResultSet(検索結果の行) |
int(処理した件数) |
| 用途 | データを読む | データを書く |
1-2. InsertServlet の作成
controller パッケージに InsertServlet.java を新規作成する。
プロジェクトを右クリック → 新規 → その他 → Web → サーブレット
パッケージ:controller、クラス名:InsertServlet
生成されたコードを以下の内容にすべて置き換える:
package controller;
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;
import dao.UserDao;
import dto.User;
/**
* データベースにユーザーを1件INSERTするサーブレット。
*
* ステップ1の学習用: フォームを使わず、Javaコードから直接データを登録する。
* ブラウザで /insert にアクセスするだけで INSERT が実行される。
*
* URLマッピング: /insert(web.xmlで設定)
*/
public class InsertServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* GETリクエストの処理。/insert にアクセスすると呼ばれる。
*
* 処理の流れ:
* Userオブジェクト作成 → UserDao.insert() でDB登録 → hello.jsp で結果表示
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 登録するデータをJavaコードで直接作成(ステップ2以降ではフォームから受け取る)
User user = new User();
user.setEmail("yamada@example.com");
user.setName("山田花子");
user.setPassword("pass123");
// DAOのinsertメソッドでデータベースに登録
// 成功なら true、失敗(email重複など)なら false が返る
UserDao userDao = new UserDao();
boolean result = userDao.insert(user);
// 結果をEclipseのコンソールに表示(開発時のデバッグ用)
if (result) {
System.out.println("登録成功: " + user.getName());
} else {
System.out.println("登録失敗");
}
// hello.jsp にフォワードして画面を表示
User savedUser = userDao.getById(2);
request.setAttribute("user", savedUser);
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/hello.jsp");
dispatcher.forward(request, response);
}
}
1-3. web.xml にマッピングを追加
web.xml を開き、既存の </servlet-mapping> の下に以下を追加する。
web.xml は「どのURLにアクセスしたら、どのサーブレットが動くか」を定義する設定ファイル。
<!-- サーブレットの登録: クラス名とサーブレット名を紐づける -->
<servlet>
<servlet-name>InsertServlet</servlet-name>
<servlet-class>controller.InsertServlet</servlet-class>
</servlet>
<!-- URLマッピング: /insert にアクセスしたら InsertServlet を実行 -->
<servlet-mapping>
<servlet-name>InsertServlet</servlet-name>
<url-pattern>/insert</url-pattern>
</servlet-mapping>
web.xml の仕組み:
ブラウザで /insert にアクセス
↓
web.xml: /insert → InsertServlet(servlet-mapping で対応づけ)
↓
controller.InsertServlet.doGet() が実行される
1-4. 動作確認
- プロジェクトを右クリック → 実行 → サーバーで実行
- ブラウザで
http://localhost:8080/Hello/insertにアクセス - Eclipseのコンソールに「登録成功: 山田花子」と表示されることを確認
- Workbench で
SELECT * FROM users;を実行し、山田花子が追加されていることを確認
注意: アクセスするたびにINSERTが実行される。ただし email に UNIQUE 制約があるため、2回目以降はエラーになる。Workbench で DELETE FROM users WHERE email = 'yamada@example.com'; を実行すれば再度試せる。
ステップ 2: Webフォームを作り、入力値をサーブレットで受け取る
目的
HTMLフォームにユーザーが入力した値を、サーブレット側で受け取って画面に表示する。
まだDBには保存せず、フォーム → サーブレット → JSP の流れを理解する。
2-1. form.jsp の作成
WEB-INF フォルダを右クリック → 新規 → その他 → Web → JSPファイル →
ファイル名: form.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>
<%--
フォームの仕組み:
action = 送信先のURL。ボタンを押すとこのURLにデータが送られる
method = "post" → サーブレットの doPost() が呼ばれる
"get" → サーブレットの doGet() が呼ばれる(デフォルト)
${pageContext.request.contextPath} はアプリのルート(/Hello)を自動取得する。
これを使うことで、アプリ名が変わっても動作する。
--%>
<form action="${pageContext.request.contextPath}/form" method="post">
<table>
<tr>
<td>メールアドレス:</td>
<%-- name="email" → サーブレット側で request.getParameter("email") に対応 --%>
<td><input type="email" name="email" required></td>
</tr>
<tr>
<td>名前:</td>
<%-- name="name" → サーブレット側で request.getParameter("name") に対応 --%>
<td><input type="text" name="name" required></td>
</tr>
<tr>
<td>パスワード:</td>
<%-- type="password" で入力値が ●●● で表示される --%>
<td><input type="password" name="password" required></td>
</tr>
</table>
<br>
<button type="submit">登録</button>
</form>
</body>
</html>
フォームとサーブレットの対応関係:
JSP側 サーブレット側
─────────────────────────────────────────────────────
name="email" → request.getParameter("email")
name="name" → request.getParameter("name")
name="password" → request.getParameter("password")
method="post" → doPost() が呼ばれる
action=".../form" → web.xml の /form にマッピングされたサーブレット
2-2. FormServlet の作成
controller パッケージに FormServlet.java を新規作成する。
package controller;
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;
/**
* ユーザー登録フォームを表示し、送信されたデータを受け取るサーブレット。
*
* このサーブレットは2つのHTTPメソッドで異なる処理を行う:
* GET → フォーム画面を表示する(ブラウザでURLにアクセスしたとき)
* POST → フォームから送信されたデータを受け取る(「登録」ボタンを押したとき)
*
* URLマッピング: /form(web.xmlで設定)
*/
public class FormServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* GETリクエスト: フォーム画面を表示する。
* ブラウザで http://localhost:8080/Hello/form にアクセスすると呼ばれる。
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/form.jsp");
dispatcher.forward(request, response);
}
/**
* POSTリクエスト: フォームから送信されたデータを受け取る。
* form.jsp の「登録」ボタンを押すと呼ばれる。
*
* データの受け渡し:
* JSPのフォーム → getParameter() で受け取り → setAttribute() でJSPに渡す
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 日本語が文字化けしないようにエンコーディングを指定
request.setCharacterEncoding("UTF-8");
// フォームの値を受け取る
// getParameter("email") の "email" は、JSP の <input name="email"> に対応
String email = request.getParameter("email");
String name = request.getParameter("name");
String password = request.getParameter("password");
// Eclipseのコンソールに表示して確認(開発時のデバッグ用)
System.out.println("受け取った値:");
System.out.println(" email: " + email);
System.out.println(" name: " + name);
System.out.println(" password: " + password);
// 受け取った値を「リクエストスコープ」に設定してJSPに渡す
// setAttribute("email", email) → JSP側で request.getAttribute("email") で取り出せる
request.setAttribute("email", email);
request.setAttribute("name", name);
request.setAttribute("password", password);
// フォーム画面に戻して入力値を表示する
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/form.jsp");
dispatcher.forward(request, response);
}
}
getParameter と getAttribute の違い:
| getParameter | getAttribute | |
|---|---|---|
| 値の送り元 | HTMLフォーム(ブラウザ → サーブレット) | setAttribute(サーブレット → JSP) |
| 使う場面 | フォーム入力を受け取る | サーブレットからJSPにデータを渡す |
| 型 | 常に String | Object(キャストが必要) |
2-3. form.jsp に受け取った値の表示を追加
form.jsp の </form> の下に以下を追加する:
<%
// サーブレットが setAttribute で渡した値を取り出す
// 初回アクセス(GET)時は setAttribute されていないので null になる
String email = (String) request.getAttribute("email");
// null でない = POST でデータが送られた → 受け取った値を表示
if (email != null) {
%>
<hr>
<h2>受け取った値</h2>
<ul>
<%-- <%= ... %> で getAttribute の値をHTMLに出力 --%>
<li>メールアドレス: <%= request.getAttribute("email") %></li>
<li>名前: <%= request.getAttribute("name") %></li>
<li>パスワード: <%= request.getAttribute("password") %></li>
</ul>
<%
}
%>
2-4. web.xml にマッピングを追加
<servlet>
<servlet-name>FormServlet</servlet-name>
<servlet-class>controller.FormServlet</servlet-class>
</servlet>
<!-- /form へのGET → FormServlet.doGet()(フォーム表示) -->
<!-- /form へのPOST → FormServlet.doPost()(データ受取) -->
<servlet-mapping>
<servlet-name>FormServlet</servlet-name>
<url-pattern>/form</url-pattern>
</servlet-mapping>
2-5. 動作確認
- サーバーを再起動
-
http://localhost:8080/Hello/formにアクセス → フォームが表示される - 各項目を入力して「登録」ボタンを押す
- 画面に「受け取った値」が表示されることを確認
- Eclipseのコンソールにも同じ値が出力されていることを確認
ステップ 3: フォーム入力をデータベースに登録する
目的
ステップ1の「DBに登録する処理」とステップ2の「フォームから値を受け取る処理」を組み合わせる。
3-1. FormServlet の doPost を修正
FormServlet.java の doPost() を以下にすべて置き換える:
/**
* POSTリクエスト: フォーム入力をデータベースに登録する。
*
* ステップ2との違い:
* ステップ2 → 受け取った値をそのままJSPに表示するだけ
* ステップ3 → 受け取った値をUserオブジェクトに詰めて、DAOでDBに登録
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
// ステップ2と同じ: フォームの値を受け取る
String email = request.getParameter("email");
String name = request.getParameter("name");
String password = request.getParameter("password");
// 【ステップ3で追加】受け取った値をDTOに詰める
// → DAOに渡すための「入れ物」に変換する
User user = new User();
user.setEmail(email);
user.setName(name);
user.setPassword(password);
// 【ステップ3で追加】DAOを使ってデータベースに登録
UserDao userDao = new UserDao();
boolean result = userDao.insert(user);
System.out.println("登録結果: " + (result ? "成功" : "失敗") + " - " + name);
// 登録後、フォーム画面に戻る
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/form.jsp");
dispatcher.forward(request, response);
}
ステップ2 → 3で変わった部分:
ステップ2: getParameter → setAttribute → JSP表示(DB無関係)
ステップ3: getParameter → User に詰める → UserDao.insert() → DB登録
3-2. FormServlet の import 文を追加
ファイル先頭の import に以下を追加する(UserDao と User を使うため):
import dao.UserDao;
import dto.User;
3-3. 動作確認
- サーバーを再起動
-
http://localhost:8080/Hello/formにアクセス - 適当な値を入力して「登録」ボタンを押す
- Eclipseのコンソールに「登録結果: 成功」と表示されることを確認
- Workbench で
SELECT * FROM users;を実行し、入力した値が追加されていることを確認
ステップ 4: 成功・失敗で画面を切り替える
目的
登録が成功したら完了画面へ、失敗したらフォームに戻してエラーメッセージを表示する。
4-1. success.jsp の作成
WEB-INF フォルダに success.jsp を新規作成する。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- User クラスを使うためにインポート --%>
<%@ page import="dto.User" %>
<%
// サーブレットが setAttribute("user", user) で渡した User オブジェクトを取り出す
// getAttribute の戻り値は Object 型なので (User) にキャストする
User user = (User) request.getAttribute("user");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登録完了</title>
</head>
<body>
<h1>登録が完了しました</h1>
<table border="1">
<tr>
<th>メールアドレス</th>
<td><%= user.getEmail() %></td>
</tr>
<tr>
<th>名前</th>
<td><%= user.getName() %></td>
</tr>
</table>
<br>
<%-- リンクをクリック → /form にGETリクエスト → FormServlet.doGet() → 空のフォーム表示 --%>
<a href="${pageContext.request.contextPath}/form">続けて登録する</a>
</body>
</html>
4-2. form.jsp にエラーメッセージ表示を追加
form.jsp の <h1>ユーザー登録フォーム</h1> の下に以下を追加する:
<%
// サーブレットが setAttribute("error", "...") でエラーメッセージを渡した場合のみ表示
// 正常時(GET / 成功時)は setAttribute されていないので null → 表示しない
String error = (String) request.getAttribute("error");
if (error != null) {
%>
<p style="color: red;"><%= error %></p>
<%
}
%>
4-3. FormServlet の doPost を最終版に修正
doPost() を以下にすべて置き換える:
/**
* POSTリクエスト: フォーム入力をDBに登録し、成功/失敗で画面を切り替える。
*
* ステップ3との違い:
* ステップ3 → 登録後、常にフォーム画面に戻る
* ステップ4 → 成功なら success.jsp、失敗なら form.jsp にエラーメッセージ付きで戻る
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String email = request.getParameter("email");
String name = request.getParameter("name");
String password = request.getParameter("password");
User user = new User();
user.setEmail(email);
user.setName(name);
user.setPassword(password);
UserDao userDao = new UserDao();
boolean result = userDao.insert(user);
// 【ステップ4で追加】登録結果によってフォワード先を切り替える
if (result) {
// 成功 → Userオブジェクトを渡して完了画面へ
request.setAttribute("user", user);
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/success.jsp");
dispatcher.forward(request, response);
} else {
// 失敗 → エラーメッセージを渡してフォーム画面に戻す
// form.jsp 側で getAttribute("error") が null でなければ赤字で表示する
request.setAttribute("error",
"登録に失敗しました。メールアドレスが重複している可能性があります。");
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/form.jsp");
dispatcher.forward(request, response);
}
}
ステップ3 → 4で変わった部分:
ステップ3: insert() → 常に form.jsp に戻る
ステップ4: insert() → true なら success.jsp、false なら form.jsp + エラーメッセージ
4-4. 動作確認
成功パターン
-
http://localhost:8080/Hello/formにアクセス - 新しいメールアドレスで入力して「登録」
- 「登録が完了しました」画面が表示される
失敗パターン
- 「続けて登録する」リンクでフォームに戻る
- 同じメールアドレスで再度「登録」
- フォーム画面に戻り、赤字で「登録に失敗しました。メールアドレスが重複している可能性があります。」が表示される
完成後のファイル構成
Hello/src/main/
├── java/
│ ├── controller/
│ │ ├── HelloServlet.java (既存: ユーザー表示)
│ │ ├── InsertServlet.java (ステップ1で追加)
│ │ └── FormServlet.java (ステップ2で追加、3・4で修正)
│ ├── dao/
│ │ └── UserDao.java (既存 + ステップ1で insert 追加)
│ └── dto/
│ └── User.java (既存: 変更なし)
└── webapp/WEB-INF/
├── web.xml (既存 + ステップ1・2でマッピング追加)
├── hello.jsp (既存: 変更なし)
├── form.jsp (ステップ2で追加、4でエラー表示追加)
└── success.jsp (ステップ4で追加)
web.xml の最終形
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
id="WebApp_ID" version="6.0">
<display-name>Hello</display-name>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>controller.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>InsertServlet</servlet-name>
<servlet-class>controller.InsertServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>InsertServlet</servlet-name>
<url-pattern>/insert</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FormServlet</servlet-name>
<servlet-class>controller.FormServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FormServlet</servlet-name>
<url-pattern>/form</url-pattern>
</servlet-mapping>
</web-app>