サーブレット/JSPとJDBCを使って、CRUD機能を実装したWebアプリの作り方を覚えるための自分用メモです。
使用環境
PC:MacBook Air 2018
OS:macOS Sonoma 14.3.1
IDE:Eclipse 2023
Webコンテナ:Tomcat 10.1.18
RDBMS:MySQL 8.3.0
DAOパターンの準備
Webアプリを作る上で、DAOパターンを使ってJDBCによるデータベースのアクセスと、CRUD機能の実装を行います。
MySQLでテーブルを用意する
今回は、簡単な顧客管理アプリを作るので、以下のようなテーブルをMySQLで作成しました。
mysql> create table clients (
-> id int auto_increment not null primary key,
-> name varchar(40) not null,
-> address varchar(100) not null,
-> email varchar(100) not null
-> );
DAOとLogicクラスを用意する
次に、用意したテーブルを操作するDAOとLogicクラスを作成します。
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import bean.ClientBean;
public class ClientDao {
private Connection con = null;
private final String url = "jdbc:mysql://localhost/mydb";
private final String user = "root";
private final String pass = ""; // 自分のrootパスワードを入力する
public boolean insert(ClientBean clientBean) {
try {
// MySQLに接続する
con = DriverManager.getConnection(url, user, pass);
// SQL文の雛形を準備する
String sql = "insert into clients(name, address, email) values(?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(sql);
// SQL文に値をセットして実行する
pstmt.setString(1, clientBean.getName());
pstmt.setString(2, clientBean.getAddress());
pstmt.setString(3, clientBean.getEmail());
int result = pstmt.executeUpdate();
// 処理結果が1以外ならfalseを返す
if(result != 1) {
return false;
}
pstmt.close();
} catch(SQLException e) {
e.printStackTrace();
return false;
} finally {
// MySQLの接続を切る
try {
if(con != null) {
con.close();
}
} catch(SQLException e) {
e.printStackTrace();
}
}
return true;
}
public List<ClientBean> selectAll() {
List<ClientBean> clientList = new ArrayList<>();
try {
// MySQLに接続する
con = DriverManager.getConnection(url, user, pass);
// SQL文を準備して実行する
String sql = "select * from clients order by id desc";
PreparedStatement pstmt = con.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
// テーブルの値をArrayListに格納する
while(rs.next()) {
String id = rs.getString("id");
String name = rs.getString("name");
String address = rs.getString("address");
String email = rs.getString("email");
ClientBean clientBean = new ClientBean(id, name, address, email);
clientList.add(clientBean);
}
pstmt.close();
} catch(Exception e) {
e.printStackTrace();
} finally {
// MySQLの接続を切る
try {
if(con != null) {
con.close();
}
} catch(SQLException e) {
e.printStackTrace();
}
}
return clientList;
}
}
package model;
import bean.ClientBean;
import dao.ClientDao;
public class AdditionalLogic {
public boolean excute(ClientBean clientBean) {
ClientDao clientDao = new ClientDao();
return clientDao.insert(clientBean);
}
}
package model;
import dao.ClientDao;
public class ClientListLogic {
public List<ClientBean> excute() {
ClientDao clientDao = new ClientDao();
return clientDao.selectAll();
}
}
Entityを用意する
また、データベースのテーブルを抽出したEntityも必要なので作成します。
package bean;
import java.io.Serializable;
public class ClientBean implements Serializable {
private String id;
private String name;
private String address;
private String email;
public ClientBean() {
}
public ClientBean(String id, String name, String address, String email) {
this.id = id;
this.name = name;
this.address = address;
this.email = email;
}
public ClientBean(String name, String address, String email) {
this.name = name;
this.address = address;
this.email = email;
}
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
テーブルのデータを表示するサーブレットを作成する
では、データベースからテーブルのデータを全て受け取って、JSPファイルで表示するサーブレットを作成します。
package servlet;
import java.io.IOException;
import bean.ClientBean;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import model.ClientListLogic;
public class ClientListServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// LogicクラスからArrayListのインスタンスを受け取る
ClientListLogic clientListLogic = new ClientListLogic();
List<ClientBean> clientList = clientListLogic.excute();
// リクエストスコープにArrayListのインスタンスを保存する
request.setAttribute("clientList", clientList);
// JSPファイルを指定してフォワード
RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/clientList.jsp");
dispatcher.forward(request, response);
}
}
次に、ArrayListのインスタンスを受け取って、テーブルのデータ一覧を表示するJSPファイルも必要なので、別途作成します。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="bean.ClientBean, java.util.List" %>
<%
List<ClientBean> clientList = (List<ClientBean>)request.getAttribute("clientList");
%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>顧客リスト</title>
</head>
<body>
<main>
<p><a href="AdditionalFormServlet">新規追加</a></p>
<table border="1">
<tr>
<th>ID</th>
<th>名前</th>
<th>住所</th>
<th>メールアドレス</th>
</tr>
<% for(ClientBean clientBean : clientList) { %>
<tr>
<td><%= clientBean.getId() %></td>
<td><%= clientBean.getName() %></td>
<td><%= clientBean.getAddress() %></td>
<td><%= clientBean.getEmail() %></td>
</tr>
<% } %>
</table>
</main>
</body>
</html>
データの追加機能を実装する
あとは、以下の記事で実装したような登録(Create)機能を実装します。
フォームを表示するサーブレットを作成する
まず、フォームを表示するサーブレットを作成します。
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;
import model.CheckAdditionalForm;
public class AdditionalFormServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// JSPファイルを指定してフォワード
RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/additionalForm.jsp");
dispatcher.forward(request, response);
}
}
それに合わせて、フォームを表示するJSPファイルを作成します。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>追加フォーム</title>
</head>
<body>
<main>
<p style="color:red">${errorMessage}</p>
<form action="AdditionalFormServlet" method="post">
<div>
<label for="name">名前</label>
<input type="text" name="name">
</div>
<div>
<label for="address">住所</label>
<input type="text" name="address">
</div>
<div>
<label for="email">メールアドレス</label>
<input type="email" name="email">
</div>
<input type="submit" value="追加">
</form>
</main>
</body>
</html>
フォームの入力内容を受け取ってセッションスコープに保存するdoPostメソッドを記述する
フォームを表示するサーブレットに、フォームの入力内容を受け取ってセッションスコープに保存し、確認画面を表示するdoPostメソッドを記述します。
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 文字コードを指定してリクエストパラメータを受け取る
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String address = request.getParameter("address");
String email = request.getParameter("email");
// リクエストパラメータの値を引数で渡してエラーメッセージを受け取る
CheckAdditionalForm checkAdditionalForm = new CheckAdditionalForm();
String errorMessage = checkAdditionalForm.checkAll(name, address, email);
if(errorMessage.isEmpty()) {
// セッションスコープにBeanのインスタンスを保存する
ClientBean clientBean = new ClientBean(name, address, email);
HttpSession session = request.getSession();
session.setAttribute("clientBean", clientBean);
// JSPファイルを指定してフォワード
RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/confirmAdditionalForm.jsp");
dispatcher.forward(request, response);
} else {
// リクエストスコープにエラーメッセージのインスタンスを保存する
request.setAttribute("errorMessage", errorMessage);
// JSPファイルを指定してフォワード
RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/additionalForm.jsp");
dispatcher.forward(request, response);
}
}
また、入力内容の値を受け取ってエラーメッセージを返すクラスを別途作成します。
package model;
public class CheckAdditionalForm {
private String errorMessage;
public CheckAdditionalForm() {
errorMessage = ""; // エラーメッセージ文頭のnullを消すため
}
public String checkAll(String name, String address, String email) {
checkName(name);
checkAddress(address);
checkEmail(email);
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 checkAddress(String address) {
checkNull(address, "住所");
// 以下チェック条件省略
}
private void checkEmail(String email) {
checkNull(email, "メールアドレス");
// 以下チェック条件省略
}
}
入力確認画面を作成する
次に、入力確認画面を表示するJSPファイルを作成します。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="bean.ClientBean" %>
<%
ClientBean clientBean = (ClientBean)session.getAttribute("clientBean");
%>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>追加確認</title>
</head>
<body>
<main>
<p>名前:<%= clientBean.getName() %></p>
<p>住所:<%= clientBean.getAddress() %></p>
<p>メールアドレス:<%= clientBean.getEmail() %></p>
<p><a href="AdditionalFormServlet">戻る</a></p>
<p><a href="AdditionalServlet">追加</a></p>
</main>
</body>
</html>
データ追加用のサーブレットと結果画面を作成する
次に、データ追加用のサーブレットを作成します。
package servlet;
import java.io.IOException;
import bean.ClientBean;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import model.AdditionalLogic;
public class AdditionalServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// セッションスコープからBeanのインスタンスを受け取る
HttpSession session = request.getSession();
ClientBean clientBean = (ClientBean)session.getAttribute("clientBean");
// LogicにBeanのインスタンスを渡して処理結果を受け取る
AdditionalLogic additionalLogic = new AdditionalLogic();
if(additionalLogic.excute(clientBean)) {
// JSPファイルを指定してフォワード
RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/succeedInAdd.jsp");
dispatcher.forward(request, response);
} else {
// JSPファイルを指定してフォワード
RequestDispatcher dispatcher = request.getRequestDispatcher("WEB-INF/jsp/failInAdd.jsp");
dispatcher.forward(request, response);
}
}
}
それに合わせて、登録結果画面を表示するJSPファイルを作成します。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>追加完了</title>
</head>
<body>
<main>
<p>顧客の追加が完了しました。</p>
<p><a href="ClientListServlet">顧客リスト画面に戻る</a></p>
</main>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>追加失敗</title>
</head>
<body>
<main>
<p>顧客の追加ができませんでした。</p>
<p><a href="ClientListServlet">顧客リスト画面に戻る</a></p>
</main>
</body>
</html>
Eclipseから実行してみる
Eclipseで制作した場合は、サーブレットを右クリック→「実行」からTomCatで実行します。
新規追加した顧客データが顧客リストのページに反映されればOKです。
次回の学習に向けて
次回は、追加した顧客データをWeb上で更新・削除できるように、顧客リストのページに更新・削除ボタンを追加します。