14
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【SpringBoot入門】フォームのバリデーションチェック

Posted at

#目的

Spring Quickstart Guideを取り組み終えた方、SpringBootを学び始めた方、復習をしたい方に向けて、

公式ガイドValidating Form Inputを実際に取り組み学んだことを共有します。

完成形はこちらになります。

名前と年齢を入力するフォームがあり、
スクリーンショット 2020-07-09 14.05.32.png

不正な値が入力したままSubmitボタンが押されるとエラーメッセージを表示して、
スクリーンショット 2020-07-09 14.05.40.png

有効な値が入力されている場合は、別の画面へと遷移出来るように実装していきます。
スクリーンショット 2020-07-09 14.12.54.png

開発環境、これまでのおさらいは以下になります。

開発環境
OS: macOS Mojave バージョン10.14.6
テキストエディタ: Visual Studio Code(以下VSCode)
Java: 11.0.2

QuickstartGuideのおさらいはこちらから
Building a RESTful Web Service編のおさらいはこちらから
Consuming a RESTful Web Service編のおさらいはこちらから
Accessing Data with JPA編のおさらいはこちらから
Handling Form Submission編のおさらいはこちらから

#1.SpringBoot projectを始めよう!

まずは、spring initializr にアクセスします。

1.ADD DEPENDENCIESボタンをクリックして、Spring WebThymeleafを追加。
2.Artifact, Nameは、validating-form-inputに変更。
3.Javaを11に変更。

そしてGENERATEボタンをクリックしてZipファイルをダウンロードします。

スクリーンショット 2020-07-09 14.25.27.png

ダウンロードしたZipファイルを展開したら準備完了です。

#2.コードを追加しよう!

先ほどのフォルダをVSCodeで開きます。
拡張機能のJava Extension Packのインストールの推奨します。と言われるのでインストールしておきましょう。

スクリーンショット 2020-06-30 10.08.25.png

##PersonForm.javaを作成しよう!

src/main/java/com/example/validatingforminput/ にPersonForm.javaファイルを作成します。

スクリーンショット 2020-07-09 14.30.13.png

公式を参考にコードを追加します。

PersonForm.java
package com.example.validatingforminput;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class PersonForm {

  @NotNull
  @Size(min=2, max=30)
  private String name;

  @NotNull
  @Min(18)
  private Integer age;

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Integer getAge() {
    return age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public String toString() {
    return "Person(Name: " + this.name + ", Age: " + this.age + ")";
  }
}

追加したコードを深掘りしていきます。

###①@NotNull@Size

PersonForm.java
@NotNull
@Size(min=2, max=30)
private String name;

String型のname変数を宣言時に2つバリデーションのアノテーションを付与しています。

@NotNullは、nullを許可しません。あくまでnullは許可しないだけで、空文字や空白は許可されるので注意してください。

@Sizeは、()の中で指定したmin以上max以下であるかを検証しています。
今回は、@Size(min=2, max=30)ですので、2文字以上30文字以下ではないとエラーになります。

###②@Min

PersonForm.java
@NotNull
@Min(18)
private Integer age;

Integer型のage変数を宣言時に2つバリデーションのアノテーションを付与しています。(1つは上述の@NotNull

@Minは、()の中に記述した値より小さいかどうか検証しています。
今回は、@Min(18)ですので、18未満はエラーになります。

###③ゲッター/セッター、toStringメソッド

PersonForm.java
public String getName() {
  return this.name;
}

public void setName(String name) {
  this.name = name;
}

public Integer getAge() {
  return age;
}

public void setAge(Integer age) {
  this.age = age;
}

public String toString() {
  return "Person(Name: " + this.name + ", Age: " + this.age + ")";
}

変数name、ageの値を取得、変更するためのゲッター/セッターメソッドを定義しています。
また、name、ageを文字列として表示するためのtoStringメソッドを定義しています。(今回使用していない気がしますが、デバッグ用なのかな?)

##pom.xmlにvalidationの依存関係を追加しよう!

公式ガイドには記載がなかったのですが、Spring Boot 2.3以上の時は、
PersonForm.javaimport javax.validation.constraints.〇〇がエラーになります。
(Spring Boot2.3 Relealse Notes)

以下をdependenciesに追加してください。

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

スクリーンショット_2020-07-09_15_38_58.png

##WebController.javaを作成しよう!

src/main/java/com/example/validatingforminput/ にWebController.javaファイルを作成します。

スクリーンショット 2020-07-09 15.41.24.png

公式を参考にコードを追加します。

WebController.java
package com.example.validatingforminput;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


@Controller
public class WebController implements WebMvcConfigurer {

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/results").setViewName("results");
  }

  @GetMapping("/")
  public String showForm(PersonForm personForm) {
    return "form";
  }

  @PostMapping("/")
  public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {
      return "form";
    }

    return "redirect:/results";
  }
}

追加したコードを深掘りしていきます。

###①WebMvcConfigurerインターフェースとaddViewControllersメソッド

WebController.java
@Controller
public class WebController implements WebMvcConfigurer {

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/results").setViewName("results");
  }

 // 以下略
}

WebMvcConfigurerインターフェースを実装、addViewControllersメソッドをオーバーライドしています。

http://localhost:8080/resultsというURLの時、results.htmlというテンプレートを参照するように設定していると解釈しています。
URLとテンプレートがマッピングされるようにしているみたいです。results.htmlの実装は後ほど。

###②showFormメソッド

WebController.java
@GetMapping("/")
public String showForm(PersonForm personForm) {
  return "form";
}

@GetMappingは、http://localhost:8080/でGETリクエストがあった時、showFormメソッドを呼ぶためのアノテーションです。
引数にPersonFormを受け取っています。メソッドの戻り値である、form.htmlのform属性でPersonFormを関連づける事ができます。
form.htmlの実装は後ほど。

###③checkPersonInfoメソッド

WebController.java
@PostMapping("/")
public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) {

  if (bindingResult.hasErrors()) {
    return "form";
  }

  return "redirect:/results";
}

@PostMappingは、http://localhost:8080/でPOSTリクエストがあった時、checkPersonInfoメソッドを呼ぶためのアノテーションです。
1つ目の引数@Valid PersonForm personFormは入力されたデータの検証をしています。
2つ目の引数BindingResult bindingResultは、入力されたデータと検証結果(エラーがあるかどうか)を保持するためのアノテーションです。

bindingResult.hasErrors()が書かれているif文では、エラーがあるかどうかを確認しています。
もしエラーがある場合、form.htmlをエラーメッセージと入力されていた値と共に再描画します。

エラーが無ければ、http://localhost:8080/resultsにリダイレクトされます。

##form.htmlを作成しよう!

src/main/resources/templates/ にform.htmlファイルを作成します。

スクリーンショット 2020-07-10 10.18.06.png

公式を参考にコードを追加します。

form.html
<html xmlns:th="http://www.thymeleaf.org">
  <body>
      <form action="#" th:action="@{/}" th:object="${personForm}" method="post">
        <table>
          <tr>
            <td>Name:</td>
            <td><input type="text" th:field="*{name}" /></td>
            <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td>
          </tr>
          <tr>
            <td>Age:</td>
            <td><input type="text" th:field="*{age}" /></td>
            <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</td>
          </tr>
          <tr>
            <td><button type="submit">Submit</button></td>
          </tr>
        </table>
      </form>
  </body>
</html>

nameとageを入力するフォーム画面ですね。

追加したコードのthymeleafの記述について深掘りしていきます。

thymeleafとは、springbootで扱う事が出来るテンプレートエンジンです。th:〇〇と記述します。
日本語で書かれたthymeleafチュートリアルもあります!

th:action

formタグのaction属性の内容を置換しています。記述の仕方は、th:action="@{}"です。
method="post"となっているので、Submitボタンが押された時にWebControllerのcheckPersonInfoメソッドが呼ばれます。

th:object

th:objectでオブジェクトを指定しています。これにより、オブジェクト内の変数の参照の仕方がpersonForm.nameではなく、*{name}のような記述方法が可能になります。

th:field

th:objectで指定したオブジェクト内の変数を表示するためにth:field="*{変数名}"と記述します。
今回は、PersonFormクラスの中にname、ageがあるので、th:field="*{name}"th:field="*{age}"となります。
また、th:field="*{変数名}"の中に記述した変数名がinputのid属性とname属性になります。

th:if

th:if=条件と記述します。trueであった場合、そのタグ、子要素が表示されます。
今回の条件は、エラーがあった場合trueになります。

th:errors

th:errors="*{変数名}"と記述します。エラーがあった場合のエラーメッセージが表示されます。
th:ifとth:errorsでエラーの有無を確認して、エラーメッセージ表示する領域を確保している感じですね。

##results.htmlを作成しよう!

src/main/resources/templates/ にresults.htmlファイルを作成します。

スクリーンショット 2020-07-10 11.11.36.png

公式を参考にコードを追加します。

results.html
<html>
  <body>
    Congratulations! You are old enough to sign up for this site.
  </body>
</html>

form画面で不正な値が入力されることが無ければこちらの画面に遷移します。

#3.実行してみよう!

アプリケーション実行の準備が出来たので確認しましょう。

ターミナルで以下のコマンドを入力してEnterしてください。

ターミナル
$ ./mvnw spring-boot:run

そして、http://localhost:8080/にアクセスすると以下のフォーム画面が表示されるはずです。(form.htmlが表示される)

スクリーンショット 2020-07-09 14.05.32.png

nameに1文字、ageに18未満の数値を入力して、Submitボタンを押すとエラーメッセージが表示されます。

スクリーンショット 2020-07-10 13.38.34.png

スクリーンショット 2020-07-10 13.38.46.png

ageに何も入力せずにSubmitボタンを押してもエラーメッセージが表示されます。

スクリーンショット 2020-07-10 13.41.09.png

nameに2文字以上、ageを18以上の数値を入力して、Submitボタンを押すとresult画面(result.html)が表示されます。

スクリーンショット 2020-07-10 13.45.01.png

スクリーンショット 2020-07-10 13.45.07.png

お疲れ様でした!完成です!

#参考サイト

Spring Bootで入力値の検証
ビュー名を返すだけのControllerなら、Controllerは別にいらないらしいよ!
検証とエラーメッセージ

14
19
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
14
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?