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>チェックＯＫです。</p>
	</body>
</html>
```

実行してみます。

http://localhost:8080/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/246741/dc0f6b67-0ff5-4602-8518-9a7fcf455661.png)

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/246741/366727ea-ff86-84fd-ad3f-11e0b7ccad92.png)

正しい入力にしてみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/246741/954aae9e-4e15-e5f4-2c74-5aec126a1b32.png)

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