基本 ローカル(Spring Boot) 約35分

fetch で API を呼び出す一覧画面を作る

Spring Boot の REST API を fetch で呼び出し、一覧表示・追加・削除ができる CRUD 画面を作る。

ここまでで REST API とデータベースが動いています。最後のステップとして、ブラウザから API を呼び出す画面を作り、データの一覧表示・追加・削除ができるようにします。

fetch の回とフォームの回で学んだパターンをそのまま使います。

完成イメージ

画面には次の要素があります。

  • 社員一覧テーブル(名前・部署・削除ボタン)
  • 新規追加フォーム(名前・部署の入力欄と追加ボタン)

操作の流れは「フォームで入力 → API を呼び出し → テーブルを再描画」です。

HTML ファイルの配置場所

Spring Boot は src/main/resources/static/ フォルダに置いたファイルをそのまま配信します。ここに index.html を作成します。

src/main/resources/static/index.html

追加の設定は不要です。アプリ起動後に http://localhost:8080/ を開くと、この HTML が表示されます。

前回までは API を確かめるために HTML を別の場所に置き、@CrossOrigin で CORS を回避していました。今回は HTML を Spring Boot の static/ に入れることで、画面と API が同じ localhost:8080 から配信されます。オリジンが同じなので CORS の問題は起きず、@CrossOrigin も不要になります。

HTML のひな形

index.html を次の内容で作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>社員管理</title>
    <style>
        body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
        th { background: #f5f5f5; }
        input { padding: 6px; margin-right: 8px; }
        button { padding: 6px 12px; }
    </style>
</head>
<body>
    <h1>社員管理</h1>
    <table>
        <thead>
            <tr><th>ID</th><th>名前</th><th>部署</th><th></th></tr>
        </thead>
        <tbody id="employee-list"></tbody>
    </table>

    <h2>新規追加</h2>
    <form id="add-form">
        <input type="text" id="name-input" placeholder="名前" required>
        <input type="text" id="dept-input" placeholder="部署" required>
        <button type="submit">追加</button>
    </form>

    <script src="app.js"></script>
</body>
</html>

ポイントは2つです。

  • <tbody id="employee-list"> — JavaScript から行を追加する場所
  • <form id="add-form"> — 送信イベントを JavaScript で処理する

一覧を取得して表示する

src/main/resources/static/app.js を作成します。まず一覧取得の部分です。

const API_URL = "/api/employees";

async function loadEmployees() {
    const response = await fetch(API_URL);
    const employees = await response.json();

    const tbody = document.getElementById("employee-list");
    tbody.innerHTML = "";

    for (const emp of employees) {
        const row = document.createElement("tr");
        row.innerHTML =
            "<td>" + emp.id + "</td>" +
            "<td>" + emp.name + "</td>" +
            "<td>" + emp.department + "</td>" +
            '<td><button onclick="deleteEmployee(' + emp.id + ')">削除</button></td>';
        tbody.appendChild(row);
    }
}

loadEmployees();

loadEmployees は fetch の回と同じパターンです。

  • fetch(API_URL) で GET リクエストを送る
  • JSON を配列として受け取る
  • for ループで1行ずつ <tr> を作り、<tbody> に追加する

tbody.innerHTML = "" で古い行をクリアしてから再描画しています。

API の URL が /api/employees になっていることに注目してください。HTML と API が同じ localhost:8080 から配信されるため、ドメイン部分を省略できます。前の回で説明した CORS の問題も起きません。

新規追加を実装する

app.js に次のコードを追加します。

document.getElementById("add-form").addEventListener("submit", async function(event) {
    event.preventDefault();

    const name = document.getElementById("name-input").value;
    const department = document.getElementById("dept-input").value;

    await fetch(API_URL, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: name, department: department })
    });

    document.getElementById("name-input").value = "";
    document.getElementById("dept-input").value = "";

    loadEmployees();
});

フォームの回で学んだパターンがそのまま使えます。

  1. event.preventDefault() でページ遷移を止める
  2. 入力値を取得して JSON に変換する
  3. fetchmethod: "POST" で送信する
  4. 入力欄をクリアして loadEmployees() で再描画する

削除を実装する

app.js に次のコードを追加します。

async function deleteEmployee(id) {
    await fetch(API_URL + "/" + id, {
        method: "DELETE"
    });
    loadEmployees();
}

削除ボタンのクリックで deleteEmployee(id) が呼ばれます。DELETE リクエストを送った後、loadEmployees() で一覧を更新します。

app.js の全体

ここまでのコードを1つにまとめます。

const API_URL = "/api/employees";

async function loadEmployees() {
    const response = await fetch(API_URL);
    const employees = await response.json();

    const tbody = document.getElementById("employee-list");
    tbody.innerHTML = "";

    for (const emp of employees) {
        const row = document.createElement("tr");
        row.innerHTML =
            "<td>" + emp.id + "</td>" +
            "<td>" + emp.name + "</td>" +
            "<td>" + emp.department + "</td>" +
            '<td><button onclick="deleteEmployee(' + emp.id + ')">削除</button></td>';
        tbody.appendChild(row);
    }
}

document.getElementById("add-form").addEventListener("submit", async function(event) {
    event.preventDefault();

    const name = document.getElementById("name-input").value;
    const department = document.getElementById("dept-input").value;

    await fetch(API_URL, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: name, department: department })
    });

    document.getElementById("name-input").value = "";
    document.getElementById("dept-input").value = "";

    loadEmployees();
});

async function deleteEmployee(id) {
    await fetch(API_URL + "/" + id, {
        method: "DELETE"
    });
    loadEmployees();
}

loadEmployees();

動作確認

アプリを起動します。

./mvnw spring-boot:run

ブラウザで http://localhost:8080/ を開くと、初期データ3件が表示されます。

社員管理画面の初期表示

確認する操作は次の3つです。

  1. 一覧表示 — テーブルに ID・名前・部署が表示される
  2. 追加 — フォームに名前と部署を入力して「追加」を押すと、テーブルに行が増える
  3. 削除 — 「削除」ボタンを押すと、該当行が消える

H2 コンソール(http://localhost:8080/h2-console)でも SELECT * FROM EMPLOYEE を実行すると、画面の操作がデータベースに反映されていることを確認できます。

編集(PUT)について

この記事では編集機能を省略しました。実装するには「行をクリックしたらフォームに値を入れ、PUT で送信する」という処理が必要です。考え方は POST と同じで、method: "PUT" に変えて ID をURLに含めるだけです。余力があれば挑戦してみてください。

カリキュラム全体のふりかえり

このコースでは次のステップで進めてきました。

コース学んだこと
Java 基礎変数・型・条件分岐・ループ・メソッド
Java オブジェクト指向クラス・フィールド・ArrayList
開発環境ローカル環境での開発(VS Code・javac・jar)
フロントエンドHTML・CSS・JavaScript・fetch
DB / SQLテーブル・SQL の CRUD・JOIN
Spring BootREST API・JPA・画面連携

最後に作った CRUD 画面は小さなアプリですが、Web アプリケーションの基本構造がすべて含まれています。

  • フロントエンド が画面を描画し、ユーザー操作を受け取る
  • API がリクエストを処理し、レスポンスを返す
  • データベース がデータを永続化する

この「フロント → API → DB」の3層構造は、実務の Web アプリケーションでもそのまま使われます。ここから先は、フレームワーク(React、Spring Security など)や本番用データベース(MySQL、PostgreSQL)を学ぶことで、実務レベルのアプリケーション開発に進めます。