[Java] [Introduction to Spring Boot] Form validation check

4 minute read

Purpose

For those who have completed Spring Quickstart Guide, those who have started learning Spring Boot, and those who want to review,

I will share what I learned by actually working on the official guide Validating Form Input.

Here is the completed form.

There is a form to enter your name and age, ![Screenshot 2020-07-09 14.05.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/d0bef22f-dd42-df35-a5e6-(04ee1d7b28a2.png)

If the Submit button is pressed with an invalid value entered, an error message will be displayed and ![Screenshot 2020-07-09 14.05.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/24792711-980a-c493-9a79-(d3e2a0be25ce.png)

If a valid value has been entered, we will implement it so that you can transition to another screen. ![Screenshot 2020-07-09 14.12.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/a8bc15dd-6017-7f48-d434-(a1eaf76e9184.png)

The development environment, the review so far is as follows.

Development environment


OS: macOS Mojave version 10.14.6
Text Editor: Visual Studio Code (VSCode)
Java: 11.0.2

Review of Quickstart Guide is here Review of Building a RESTful Web Service Review of Consuming a RESTful Web Service Review of Accessing Data with JPA Click here for a review of the Handling Form Submission

Let’s start #1.SpringBoot project!

First, access spring initializr.

  1. Click the ADD DEPENDENCIES button and add Spring Web and Thymeleaf. 2.Artifact, Name changed to validating-form-input.
  2. Change Java to 11.

Then click the GENERATE button to download the Zip file.

Screenshot 2020-07-09 14.25.27.png

Extract the downloaded Zip file and you’re ready to go.

2.Let’s add code!

Open the previous folder with VS Code. We recommend that you install the extension Java Extension Pack. It is said that you should install it.

![Screenshot 2020-06-30 10.08.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/80331ebc-b6e3-af7b-181a-(3c8921288b00.png)

Let’s create PersonForm.java!

Create a PersonForm.java file in src/main/java/com/example/validatingforminput/.

![Screenshot 2020-07-09 14.30.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/a62700fe-fd88-4f68-3a2c-(911bb7f877a1.png)

Add the code by referring to the formula.

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 + ")";
  }
}

We will dig deeper into the added code.

@NotNull and @Size

PersonForm.java


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

Two validation annotations are added when declaring the String type name variable.

@NotNull does not allow null**. Please note that null is not allowed and empty characters and spaces are allowed.

@Size verifies whether it is min or more and max or less specified in (). This time, it is @Size(min=2, max=30), so if it is not more than 2 characters and less than 30 characters, an error will occur.

@Min

PersonForm.java


@NotNull
@Min(18)
private Integer age;

Two validation annotations are added when declaring an Integer type age variable. (One is @NotNull above)

@Min verifies whether it is less than the value written in (). This time it is @Min(18), so less than 18 will result in an error.

③ Getter/setter, toString method

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 + ")";
}

Defines getter/setter methods to get and change the values of variables name and age. Also, toString method to display name and age as a character string is defined. (I don’t think I’m using it this time, but is it for debugging?)

Let’s add the validation dependency to ##pom.xml!

Although there was no description in the official guide, when Spring Boot 2.3 or above, An error occurs in import javax.validation.constraints.〇〇 of PersonForm.java. (Spring Boot2.3 Relealse Notes)

Add the following to dependencies.

pom.xml


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

![Screenshot _2020-07-09_15_38_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/65bfada7-b531-f6e2-5e4f-3750df9280c5.(png)

Let’s create WebController.java!

Create WebController.java file in src/main/java/com/example/validatingforminput/.

![Screenshot 2020-07-09 15.41.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/d697f855-e7a1-de69-4f59-(01ce7d9a20de.png)

Add the code by referring to the formula.

java:WebController.javapackage 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してください。

ターミナル

```terminal

$ ./mvnw spring-boot:run ```Then, when you access http://localhost:8080/, the following form screen should be displayed. (Form.html is displayed)

![Screenshot 2020-07-09 14.05.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/b2075fd2-cb6a-44d7-99e5-(181ee31452ad.png)

If you enter one character for **name and a number less than 18 for age and press the Submit button, an error message will be displayed. **

![Screenshot 2020-07-10 13.38.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/5bb4c39d-f2d7-cd5f-c967-(060c4a2d6559.png)

![Screenshot 2020-07-10 13.38.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/259e3294-53d5-edfa-ffea-(875c3dbdf985.png)

If you press the Submit button without entering anything in **age, an error message will be displayed. **

![Screenshot 2020-07-10 13.41.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/4e8332f4-e23b-edd6-2da4-(564dec4f9a04.png)

Enter a number of 2 or more characters and age of 18 or more for **name and press the Submit button to display the result screen (result.html). **

![Screenshot 2020-07-10 13.45.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/d8e5134b-bdd8-11a6-07bc-(1d9356a45cde.png)

![Screenshot 2020-07-10 13.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555244/17df7f90-e863-43fd-90c2-(ef4ea2313da4.png)

Thank you for your hard work! done!

Reference site

Validating input value with Spring Boot If you just want to return the view name, you don’t need a Controller! Verification and error message