Spring Boot

Spring Boot + Thymeleafで新規登録画面を作成する

はじめに

Javaの人気フレームワーク「Spring Boot」と「Spring Boot」と相性の良いテンプレートエンジン「Thymeleaf」を使用して登録画面を作成する方法を紹介します。

また、データベースへの登録は「Spring Data JPA」を使用しています。

本記事で作成する「ユーザー新規登録」画面のイメージは以下のとおり。

登録画面のイメージ

 

「キャンセル」または「登録」ボタン押下で「ユーザー情報一覧」画面に戻るようにします。

一覧画面のイメージ

一覧画面作成の記事はこちら

[テーブル定義]

物理名 論理名 データ型 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 論理削除した日時

スポンサーリンク

開発環境

開発環境は以下のとおり。

開発環境 名称 説明
開発言語 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
       |    |
       |    |___dto
       |    |    |
       |    |    |___UserRequest.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.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.demo.dto.UserRequest;
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) {
    model.addAttribute("userRequest", new UserRequest());
    return "user/add";
  }

  /**
   * ユーザー新規登録
   * @param userRequest リクエストデータ
   * @param model Model
   * @return ユーザー情報一覧画面
   */
  @RequestMapping(value = "/user/create", method = RequestMethod.POST)
  public String create(@Validated @ModelAttribute UserRequest userRequest, BindingResult result, Model model) {

    if (result.hasErrors()) {
      // 入力チェックエラーの場合
      List<String> errorList = new ArrayList<String>();
      for (ObjectError error : result.getAllErrors()) {
        errorList.add(error.getDefaultMessage());
      }
      model.addAttribute("validationError", errorList);
      return "user/add";
    }
    // ユーザー情報の登録
    userService.create(userRequest);
    return "redirect:/user/list";
  }

  /**
   * ユーザー情報詳細画面を表示
   * @param id 表示するユーザーID
   * @param model Model
   * @return ユーザー情報詳細画面
   */
  @GetMapping("/user/{id}")
  public String displayView(@PathVariable Long id, Model model) {
    return "user/view";
  }
}

createメソッドで"userRequest"が存在しないというエラーが発生する場合は「model.addAttribute("validationError", errorList);」の下に「model.addAttribute("userRequest", UserRequest);」を追加してください。

 

コントロールクラスに用意しているメソッドは以下です。

メソッド名 説明
displayList HTTP GETで「http://localhost:8080/user/list」にアクセスしたときに動き出すメソッド。「ユーザー情報一覧」画面の初期表示をおこなう。
displayAdd 「ユーザー情報一覧」画面の「新規登録はこちら」ボタン押下時に動き出すメソッド。「ユーザー新規登録」画面の初期表示をおこなう。
create 「ユーザー新規登録」画面の「登録」ボタン押下時に動き出すメソッド。ユーザー情報の登録処理をおこなう。
displayView 「ユーザー情報一覧」画面の「詳細」ボタン押下時に動き出すメソッド。「ユーザー情報詳細画面ダミー」画面の初期表示をおこなう。

サービスクラス(UserService.java)

サービスクラスの内容は以下のとおり。

データベース接続は「Spring Data JPA」、トランザクション管理は「@Transactional」のアノテーションを使用しています。「@Transactional」を使うことで登録に成功すればコミット、失敗してExceptionが発生すればロールバックを自動で行ってくれます。

package com.example.demo.service;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.demo.dto.UserRequest;
import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;

/**
 * ユーザー情報 Service
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserService {
  /**
   * ユーザー情報 Repository
   */
  @Autowired
  private UserRepository userRepository;

  /**
   * ユーザー情報 全検索
   * @return 検索結果
   */
  public List<User> searchAll() {
    return userRepository.findAll();
  }

  /**
   * ユーザー情報 新規登録
   * @param user ユーザー情報
   */
  public void create(UserRequest userRequest) {
    Date now = new Date();
    User user = new User();
    user.setName(userRequest.getName());
    user.setAddress(userRequest.getAddress());
    user.setPhone(userRequest.getPhone());
    user.setCreateDate(now);
    user.setUpdateDate(now);
    userRepository.save(user);
  }
}

サービスクラスに用意しているメソッドは以下です。

メソッド 説明
searchAll データベースからユーザー情報を取得する
create データベースに画面からの入力データを登録する

エンティティクラス(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> {}

スポンサーリンク

Data Transfer Object(UserRequest.java)

登録画面からのリクエストデータを格納するオブジェクトクラスは以下のとおり。

入力チェックは「Bean Validation」を使用しています。「@NotEmpty」や「@Size」などを定義することで簡単に入力チェックを実装することができます。

package com.example.demo.dto;

import java.io.Serializable;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import lombok.Data;

/**
 * ユーザー情報 リクエストデータ
 */
@Data
public class UserRequest implements Serializable {
  /**
   * 名前
   */
  @NotEmpty(message = "名前を入力してください")
  @Size(max = 100, message = "名前は100桁以内で入力してください")
  private String name;
  /**
   * 住所
   */
  @Size(max = 255, message = "住所は255桁以内で入力してください")
  private String address;
  /**
   * 電話番号
   */
  @Pattern(regexp = "0\\d{1,4}-\\d{1,4}-\\d{4}", message = "電話番号の形式で入力してください")
  private String phone;
}

 

Bean ValidationはSpring Bootのバージョンが2.3.1以降の場合、依存関係に「spring-boot-starter-validation」の追加が必要です。

gradleの場合は「build.gradle」に以下を追加。

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-validation'
}

mavenの場合は「pom.xml」に以下を追加。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

フロントエンド(クライアント)側のソースコード

ユーザー新規登録画面(add.html)

共通ヘッダ(head.html)、ユーザー情報一覧画面(list.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">
    <div th:if="${validationError}" th:each="error : ${validationError}">
      <label class="text-danger" th:text="${error}"></label>
    </div>
    <h1>ユーザー新規登録</h1>
    <form th:action="@{/user/create}" th:object="${userRequest}" th:method="post">

      <div class="form-group">
        <label>名前:<span class="text-danger">※</span></label>
        <input type="text" th:field="*{name}" class="form-control">
      </div>

      <div class="form-group">
        <label>住所:</label>
        <input type="text" th:field="*{address}" class="form-control">
      </div>

      <div class="form-group">
        <label>電話番号:<span class="text-danger">※</span></label>
        <input type="text" th:field="*{phone}" class="form-control">
      </div>
      <br />
      <div class="text-center">
        <a href="/user/list" class="btn btn-secondary">キャンセル</a>
        <input type="submit" value=" 登録 " class="btn btn-primary">
      </div>
    </form>
  </div>
</body>
</html>

動作確認

Spring Bootプロジェクトを実行して http://localhost:8080/user/list へアクセスします。

一覧画面のイメージ

ユーザー情報一覧画面が表示されるので、「新規登録はこちら」ボタンを押下します。

登録画面のイメージ

ユーザー新規登録画面が表示されるので、ユーザー情報を入力し「登録」ボタンを押下すると、ユーザー情報一覧画面に戻り登録した内容が表示されていればOKです。

※ユーザー情報の入力に誤りがある場合は、次のようにユーザー情報一覧画面には遷移せず、エラーメッセージがユーザー新規登録画面の上部に表示される。

入力チェックエラーの場合

helpful