SpringBoot + Thymeleafで相関チェックする


SpringbootのBean Validationを使って項目間の相関チェックを実装します

この記事では、期間を入力するページで、終了日が、開始日よりも小さい場合のチェックを試します。

相関チェックを行うにあたり、@AssertTrueアノテーションを使います

1.環境
Eclipse 4.7(Oxygen)
Java 8
springBootVersion = '1.5.13.BUILD-SNAPSHOT'

2.構成

├─java
│  └─com
│      └─stone
│          └─check
│                  HeloController.java
│                  SampleCheckApplication.java
│                  SampleForm.java
│                  ServletInitializer.java
└─resources
    │  application.properties
    ├─static
    └─templates
            index.html
            top.html

3.form

SampleForm.java
import javax.validation.constraints.AssertTrue;
import lombok.Data;
@Data
public class SampleForm {
    private int startdate;
    private int enddate;
    @AssertTrue(message="開始日は終了日以前を入力してください。")
    public boolean isDateValid() {
        if (enddate >= startdate) return true;
        return false;
    }
}

Point
@AssertTrue」アノテーションをつけて、boolean型のメソッドを作成します。メソッドの最初は「is」をつけておきます。

4.Controller

HeloController.java
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HeloController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(
            @ModelAttribute("form") SampleForm form,
            Model model){
        form.setStartdate(20180401);
        form.setEnddate(20180401);
        return "index";
    }
    @RequestMapping(value = "/check", method = RequestMethod.POST)
    public String check(
            @ModelAttribute("form") @Valid SampleForm form,
            BindingResult result, Model model) {
        if (result.hasErrors()) {
            model.addAttribute("errmsg", "エラーがあります。修正してください。");
            return "index";
        }
        return "top";
    }
}

最初のページ(index.html)で期間を入力し、エラーがある場合はページにエラーをセットして再描画し、エラーがなければ次のページ(top.html)に遷移します。

Point

画面がPostされた場合のメソッドの引数のフォームオブジェクトに「@Valid」アノテーションをつけ、BindingResult クラスでvalidationをバインドします。

@ModelAttribute("form") @Valid SampleForm form,
            BindingResult result

5.thymeleaf
(1)index.html

index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Springboot</title>
        <meta charset="utf-8" />
    </head>
    <body>
        <form th:object="${form}" th:action="@{/check}" th:method="post">
            <!-- 入力に何かのエラーがあった場合のメッセージを表示する。 -->
            <p th:if="${errmsg} != null" th:text="${errmsg}" style="color:red;"></p>
            <label>開始日</label>
            <input type="text" th:field="*{startdate}"/>
            <label>終了日</label>
            <input type="text" th:field="*{enddate}"/>
            <!-- 期間チェックのエラーメッセージを表示する。 -->
            <p th:if="${#fields.hasErrors('dateValid')}" th:errors="*{dateValid}" style="color:red;"></p>
            <button type="submit">チェック</button>
        </form>
    </body>
</html>

Point
全体的なエラーは、Controllerでセットした"errmsg"の値を表示
期間チェックエラーは、@asserttrueのメソッド名のis以降の項目名が変数名になっています。(今回は、isDateValidとしたので「dateValid」というエラー変数名にエラーが入っています。

(2)top.html

top.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Springboot</title>
        <meta charset="utf-8" />
    </head>
    <body>
        <p>チェックOKです。</p>
    </body>
</html>

実行してみます。

終了日を開始日より小さくしてみました。

正しい入力にしてみます。

相関チェックの実装は他の方法もいろいろあるようですが、@assertrueが一番簡単だと思います。