Spring Boot + Thymeleaf でフォーム送信から一覧表示まで完全攻略!

🎯 この記事で実現すること

名前と点数を入力フォームで送信し、それを一覧テーブルに追加表示する本格的なWebアプリケーションを作成します。前回の「表示だけ」から一歩進んで、ユーザーが実際にデータを入力できる動的なアプリに挑戦しましょう!

📱 完成イメージ

入力画面

学生情報を入力
名前: [太郎        ]
点数: [85         ]
     [追加ボタン]

一覧画面

名前 点数
太郎 85
花子 92
次郎 78

[新しい学生を登録] ← リンクで入力画面に戻る

🗂 ファイル構成

今回作成するファイルは以下の4つです:

ファイル名 役割
Student.java 名前と点数を持つモデルクラス
StudentController.java 入力フォームと一覧を処理するコントローラ
student_form.html 入力画面(フォーム)
student_list.html 一覧表示画面(テーブル形式)

🛠 実装手順

Step 1: Studentモデルクラスを拡張

前回からsetterを追加します。フォームからデータを受け取るために必要です。

ファイル: src/main/java/com/example/demo/model/Student.java

java
package com.example.demo.model;

public class Student {
    private String name;
    private int score;

    public Student() {} // フォーム用の空コンストラクタ

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    // getter(表示用)
    public String getName() {
        return name;
    }

    public int getScore() {
        return score;
    }

    // setter(フォーム受け取り用)
    public void setName(String name) {
        this.name = name;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

重要ポイント:

  • public Student() {} – 空のコンストラクタが必要
  • setName(), setScore() – フォームから値を設定するため

Step 2: StudentControllerを作成

3つの処理(フォーム表示・送信処理・一覧表示)をまとめて管理します。

ファイル: src/main/java/com/example/demo/controller/StudentController.java

java
package com.example.demo.controller;

import com.example.demo.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@Controller
public class StudentController {

    // メモリ上でデータを保持(今回は簡単のため)
    private List<Student> studentList = new ArrayList<>();

    // フォーム表示
    @GetMapping("/student/form")
    public String showForm(Model model) {
        model.addAttribute("student", new Student());
        return "student_form";
    }

    // フォーム送信処理
    @PostMapping("/student/submit")
    public String submitForm(@ModelAttribute Student student) {
        studentList.add(student);
        return "redirect:/student/list";
    }

    // 一覧表示
    @GetMapping("/student/list")
    public String showList(Model model) {
        model.addAttribute("studentList", studentList);
        return "student_list";
    }
}

処理の流れ:

  1. GET /student/form → 入力フォーム画面を表示
  2. POST /student/submit → 送信されたデータをリストに追加
  3. GET /student/list → 登録済みデータを一覧表示

Step 3: 入力フォーム画面を作成

ファイル: src/main/resources/templates/student_form.html

html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>学生情報入力</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
        }
        .form-group {
            margin-bottom: 15px;
        }
        label {
            display: inline-block;
            width: 80px;
            font-weight: bold;
        }
        input[type="text"], input[type="number"] {
            width: 200px;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        button {
            background-color: #007bff;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <h1>📝 学生情報を入力</h1>
    
    <form th:action="@{/student/submit}" th:object="${student}" method="post">
        <div class="form-group">
            <label for="name">名前:</label>
            <input type="text" th:field="*{name}" id="name" required />
        </div>
        
        <div class="form-group">
            <label for="score">点数:</label>
            <input type="number" th:field="*{score}" id="score" min="0" max="100" required />
        </div>
        
        <button type="submit">📊 一覧に追加</button>
    </form>
</body>
</html>

フォームの技術ポイント:

  • th:action="@{/student/submit}" – 送信先URL
  • th:object="${student}" – バインドするオブジェクト
  • th:field="*{name}" – Studentクラスのnameフィールドと連携
  • required – 必須入力チェック

Step 4: 一覧表示画面を作成

ファイル: src/main/resources/templates/student_list.html

html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>学生一覧</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 12px;
            text-align: center;
        }
        th {
            background-color: #f8f9fa;
            font-weight: bold;
        }
        tr:nth-child(even) {
            background-color: #f2f2f2;
        }
        .add-link {
            display: inline-block;
            background-color: #28a745;
            color: white;
            padding: 10px 20px;
            text-decoration: none;
            border-radius: 4px;
            margin-top: 20px;
        }
        .add-link:hover {
            background-color: #218838;
        }
        .empty-message {
            text-align: center;
            color: #666;
            font-style: italic;
            padding: 20px;
        }
    </style>
</head>
<body>
    <h1>📊 登録された学生一覧</h1>
    
    <div th:if="${#lists.isEmpty(studentList)}" class="empty-message">
        まだ学生が登録されていません。
    </div>
    
    <table th:unless="${#lists.isEmpty(studentList)}">
        <tr>
            <th>名前</th>
            <th>点数</th>
        </tr>
        <tr th:each="student, stat : ${studentList}">
            <td th:text="${student.name}">名前</td>
            <td th:text="${student.score}">点数</td>
        </tr>
    </table>
    
    <a th:href="@{/student/form}" class="add-link">➕ 新しい学生を登録</a>
</body>
</html>

表示の技術ポイント:

  • th:if="${#lists.isEmpty(studentList)}" – リストが空の場合の表示
  • th:unless – 条件の逆(リストが空でない場合)
  • th:each="student, stat : ${studentList}" – 繰り返し表示
  • th:href="@{/student/form}" – フォーム画面へのリンク

🔍 動作確認手順

  1. Spring Bootアプリケーションを起動
  2. ブラウザで http://localhost:8080/student/form にアクセス
  3. 名前(例:太郎)と点数(例:85)を入力
  4. 「一覧に追加」ボタンをクリック
  5. 一覧画面に遷移し、入力したデータが表示される
  6. 「新しい学生を登録」リンクで再びフォーム画面に戻れる

💡 技術解説

MVCパターンの実装

  • Model(Student): データ構造を定義
  • View(HTML): ユーザーインターフェース
  • Controller(StudentController): 処理ロジックとデータの橋渡し

Spring Bootの重要な機能

アノテーション 役割
@Controller このクラスがコントローラーであることを宣言
@GetMapping HTTP GETリクエストを処理
@PostMapping HTTP POSTリクエストを処理
@ModelAttribute フォームデータを自動でオブジェクトに変換

Thymeleafの便利な機能

属性 説明
th:action フォーム送信先URL
th:object バインドするオブジェクト
th:field フォーム要素とオブジェクトのフィールドを連携
th:each リスト要素の繰り返し表示
th:if/unless 条件分岐表示

🚀 さらなる機能拡張

この基本形ができたら、以下の機能に挑戦してみましょう:

1. データベース連携

java
// H2データベースやMySQLでデータを永続化
@Entity
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // ...
}

2. 合格判定機能

html
<!-- 点数に応じて色分け表示 -->
<td th:text="${student.score}" 
    th:class="${student.score >= 80} ? 'pass' : 'fail'">
    点数
</td>

3. バリデーション機能

java
// 入力値チェック
@NotBlank(message = "名前は必須です")
private String name;

@Min(value = 0, message = "点数は0以上で入力してください")
@Max(value = 100, message = "点数は100以下で入力してください")
private int score;

4. 削除・編集機能

  • 各行に「編集」「削除」ボタンを追加
  • RESTful URLパターンの実装

📝 まとめ

この記事では、Spring Boot + Thymeleafを使って完全な CRUD(Create, Read)操作の基礎を実装しました。

習得した技術スキル:

  • フォームデータの送受信
  • MVCアーキテクチャの実装
  • Thymeleafテンプレートエンジンの活用
  • RESTfulなURL設計の基礎

実用的なポイント:

  • ユーザー入力の受け取り方法
  • データの一時保存と表示
  • 画面間の遷移制御

このチュートリアルをマスターすれば、多くのWebアプリケーションの基本パターンが理解できます。次はデータベース連携や高度な機能に挑戦して、より実用的なアプリケーションを作ってみましょう!

次回予告: 「Spring Boot + H2データベースで永続化機能を実装しよう!」

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


最近のコメント