1
1

【サーブレット/JSP/JDBC】CRUDアプリの作り方を覚える①

Last updated at Posted at 2024-08-03

サーブレット/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クラスを作成します。

ClientDao.java
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;
    }

}
AdditionalLogic.java
package model;

import bean.ClientBean;
import dao.ClientDao;

public class AdditionalLogic {
    public boolean excute(ClientBean clientBean) {
        ClientDao clientDao = new ClientDao();
        return clientDao.insert(clientBean);
    }
}
ClientListLogic.java
package model;

import dao.ClientDao;

public class ClientListLogic {
    public List<ClientBean> excute() {
        ClientDao clientDao = new ClientDao();
        return clientDao.selectAll();
    }
}

Entityを用意する

また、データベースのテーブルを抽出したEntityも必要なので作成します。

ClientBean.java
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ファイルで表示するサーブレットを作成します。

ClientListServlet.java
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ファイルも必要なので、別途作成します。

clientList.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)機能を実装します。

フォームを表示するサーブレットを作成する

まず、フォームを表示するサーブレットを作成します。

AdditionalFormServlet.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;
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ファイルを作成します。

additionalForm.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メソッドを記述します。

AdditionalFormServlet.java
    @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);
        }
    }

また、入力内容の値を受け取ってエラーメッセージを返すクラスを別途作成します。

CheckAdditionalForm.java
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ファイルを作成します。

confirmAdditionalForm.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>

データ追加用のサーブレットと結果画面を作成する

次に、データ追加用のサーブレットを作成します。

AdditionalServlet.java
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ファイルを作成します。

succeedInAdd.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>
failInAdd.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>

Eclipseから実行してみる

Eclipseで制作した場合は、サーブレットを右クリック→「実行」からTomCatで実行します。
新規追加した顧客データが顧客リストのページに反映されればOKです。
client.jpg
client_1.jpg
client_2.jpg
client_3.jpg
client_4.jpg

次回の学習に向けて

次回は、追加した顧客データをWeb上で更新・削除できるように、顧客リストのページに更新・削除ボタンを追加します。

1
1
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
1
1