目次
はじめに
Javaのフレームワーク「Spring Boot」とテンプレートエンジン「Thymeleaf」を使用して、一覧画面を作成する手順を紹介します。
本記事で作成する「一覧画面」のイメージとテーブル定義は以下の通り。

※「新規登録はこちら」ボタンと「詳細」ボタンを押下するとダミーの画面に遷移するようになっています。
[テーブル定義]
| 物理名 | 論理名 | データ型 | NOT NULL | 説明 | 
| id | ID | BIGINT | 〇 | 主キー(AUTO_INCREMENT) | 
| name | 名前 | VARCHAR(100) | 〇 | ユーザーの名前 | 
| address | 住所 | VARCHAR(255) | ユーザーの住所 | |
| phone | 電話番号 | VARCHAR(50) | ユーザーの電話番号 | |
| update_date | 更新日時 | DATETIME | 〇 | 最終更新日時 | 
| create_date | 作成日時 | DATETIME | 〇 | 登録日時 | 
| delete_date | 削除日時 | DATETIME | 論理削除した日時 | 
■CREATE文
CREATE TABLE `sampledb`.`user` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(100) NOT NULL,
  `address` VARCHAR(255) NULL,
  `phone` VARCHAR(50) NULL,
  `update_date` DATETIME NOT NULL,
  `create_date` DATETIME NOT NULL,
  `delete_date` DATETIME NULL,
  PRIMARY KEY (`id`));■INSERT文
INSERT INTO `sampledb`.`user` (`id`, `name`, `address`, `phone`, `update_date`, `create_date`) VALUES ('1', 'テスト太郎', '東京都品川区1-1', '090-0000-0000', '2021/06/30', '2021/06/30');
INSERT INTO `sampledb`.`user` (`id`, `name`, `address`, `phone`, `update_date`, `create_date`) VALUES ('2', 'テスト次郎', '東京都渋谷区1-1', '080-0000-0000', '2021/06/30', '2021/06/30');スポンサーリンク
開発環境
開発環境は以下の通り。
| 開発環境 | 名称 | 説明 | 
| 開発言語 | Java | 人気の開発言語 | 
| 開発ツール | Eclipse | Javaでの定番開発ツール | 
| フレームワーク | Spring Boot | 人気のSpringフレームワークをベースとしたフレームワーク | 
| テンプレートエンジン | Thymeleaf | Spring Bootと相性が良いテンプレートエンジン | 
| データベース | MySQL | フリーで利用できる人気データベース | 
その他 データベースへの接続は「Spring Data JPA」、画面のデザインには「Bootstrap」を使用しています。
ディレクトリ構成
ディレクトリ構成は次の通り。
springSample
  |
  |___src.main.java
       |
       |___com.example.demo
       |    |
       |    |___controller
       |    |    |
       |    |    |__UserController.java
       |    |
       |    |___entity
       |    |    |
       |    |    |___User.java
       |    |
       |    |___repository
       |    |    |
       |    |    |___UserRepository.java
       |    |
       |    |___service
       |         |
       |         |___UserService.java
       |
       |___src.main.resources
            |
            |___templates
            |    |
            |    |___common
            |    |    |
            |    |    |___head.html 
            |    |
            |    |___user
            |         |
            |         |___add.html
            |         |
            |         |___list.html
            |         |
            |         |___view.html
            |
            |___application.propertiesバックエンド(サーバー)側のソースコード
コントローラークラス(UserController.java)
コントローラクラスの内容は以下の通り。
package com.example.demo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
/**
 * ユーザー情報 Controller
 */
@Controller
public class UserController {
  /**
   * ユーザー情報 Service
   */
  @Autowired
  private UserService userService;
  /**
   * ユーザー情報一覧画面を表示
   * @param model Model
   * @return ユーザー情報一覧画面
   */
  @GetMapping(value = "/user/list")
  public String displayList(Model model) {
    List<User> userlist = userService.searchAll();
    model.addAttribute("userlist", userlist);
    return "user/list";
  }
  /**
   * ユーザー新規登録画面を表示
   * @param model Model
   * @return ユーザー情報一覧画面
   */
  @GetMapping(value = "/user/add")
  public String displayAdd(Model model) {
    return "user/add";
  }
  /**
   * ユーザー情報詳細画面を表示
   * @param id 表示するユーザーID
   * @param model Model
   * @return ユーザー情報詳細画面
   */
  @GetMapping("/user/{id}")
  public String displayView(@PathVariable Long id, Model model) {
    return "user/view";
  }
}サービスクラス(UserService.java)
サービスクラスの内容は以下の通り。データベースとの接続は「Spring Data JPA」を使用しています。
package com.example.demo.service;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
/**
 * ユーザー情報 Service
 */
@Service
public class UserService {
  /**
   * ユーザー情報 Repository
   */
  @Autowired
  private UserRepository userRepository;
  /**
   * ユーザー情報 全検索
   * @return 検索結果
   */
  public List<User> searchAll() {
    return userRepository.findAll();
  }
}エンティティクラス(User.java)
データベースから取得したデータを格納するエンティティクラスの内容は以下の通り。@Dataアノテーションを使用して、getter、setterの定義を省略しています。
package com.example.demo.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
/**
 * ユーザー情報 Entity
 */
@Entity
@Data
@Table(name = "user")
public class User implements Serializable {
  /**
   * ID
   */
  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  /**
   * 名前
   */
  @Column(name = "name")
  private String name;
  /**
   * 住所
   */
  @Column(name = "address")
  private String address;
  /**
   * 電話番号
   */
  @Column(name = "phone")
  private String phone;
  /**
   * 更新日時
   */
  @Column(name = "update_date")
  private Date updateDate;
  /**
   * 登録日時
   */
  @Column(name = "create_date")
  private Date createDate;
  /**
   * 削除日時
   */
  @Column(name = "delete_date")
  private Date deleteDate;
}リポジトリクラス(UserRepository.java)
データベースにアクセスするためのリポジトリクラスは以下の通り。
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.demo.entity.User;
/**
 * ユーザー情報 Repository
 */
@Repository
public interface UserRepository extends JpaRepository<User, Long> {}フロントエンド(クライアント)側のソースコード
スポンサーリンク
共通ヘッダ(head.html)
共通のヘッダは次の通り。ヘッダ情報は同じなので共通で管理しています。
画面ごとに変わる「title」だけ動的に変えられるようにしています。また、画面デザインにはBootstrapを使っているので、Bootstrapのcssとjsを読み込んでいます。
<head th:fragment="head_fragment(title, scripts, links)">
  <title th:text="${title}"></title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
  <meta charset="utf-8" />
</head>ユーザー情報一覧画面(list.html)
ユーザー情報一覧画面のHTMLは以下の通り。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/head :: head_fragment(title = 'ユーザー情報一覧', scripts = ~{::script}, links = ~{::link})"></head>
<body>
  <div class="container">
    <h1>ユーザー情報一覧</h1>
    <div class="float-end">
      <a th:href="@{/user/add}" class="btn btn-primary">新規登録はこちら</a>
    </div>
    <table class="table table-striped">
      <thead>
        <tr>
          <th>ID</th>
          <th>名前</th>
          <th>住所</th>
          <th>電話番号</th>
          <th>更新日時</th>
          <th>登録日時</th>
          <th>削除日時</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr th:each="user : ${userlist}" th:object="${user}" class="align-middle">
          <td th:text="*{id}"></td>
          <td th:text="*{name}"></td>
          <td th:text="*{address}"></td>
          <td th:text="*{phone}"></td>
          <td th:text="${#dates.format(user.updateDate, 'yyyy/MM/dd')}"></td>
          <td th:text="${#dates.format(user.createDate, 'yyyy/MM/dd')}"></td>
          <td th:text="${#dates.format(user.deleteDate, 'yyyy/MM/dd')}"></td>
          <td><a th:href="@{/user/{id}(id=*{id})}" class="btn btn-secondary">詳細</a></td>
        </tr>
      </tbody>
    </table>
  </div>
</body>
</html>新規登録画面(add.html)
新規登録画面のHTMLは以下の通り。
画面遷移を確認するためのダミーHTMLです。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/head :: head_fragment(title = 'ユーザー新規登録', scripts = ~{::script}, links = ~{::link})"></head>
<body>
  <div class="container">
    <h1>新規登録画面ダミー</h1>
    <a href="/user/list">一覧に戻る</a>
  </div>
</body>
</html>ユーザー情報詳細画面(view.html)
ユーザー情報詳細画面のHTMLは以下の通り。
画面遷移を確認するためのダミーHTMLです。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org">
<head th:replace="common/head :: head_fragment(title = 'ユーザー情報詳細', scripts = ~{::script}, links = ~{::link})"></head>
<body>
  <div class="container">
    <h1>ユーザー情報詳細画面ダミー</h1>
    <a href="/user/list">一覧に戻る</a>
  </div>
</body>
</html>動作確認
Spring Bootプロジェクトを実行して http://localhost:8080/user/list へアクセスします。
一覧画面が表示され、デーベースから取得した値が一覧に表示されていれば完了です。

「新規登録はこちら」ボタン押下 → Spring Boot + Thymeleafで新規登録画面を作成する
「詳細」ボタン押下 → Spring Boot + Thymeleafで詳細画面を作成する
 
 