オブジェクトを使ってビューとコントローラの値を共有

# 目的
Spring Bootのビュー→コントローラ、コントローラ→ビューの値の共有をオブジェクトを使って実行することで、オブジェクトの理解を深める。

## 作成するもの
Spring Bootを使って作成する
/thymeleaf-inputPageにアクセスすると、入力画面が表示される。
入力画面で名前、年齢入力すると、出力画面が表示される。
MVCを使用し、入力画面と出力画面の間にはコントローラを挟む
画面とコントローラ間のデータはオブジェクトを使用する。

## ファイル一覧
- コントローラ、オブジェクト
ThymeleafController.java
- 入力画面
thymeleaf-inputPage.html
- 出力画面
thymeleaf-outputPage.html

~~~ThymeleafController.java
//import省略
@Controller
public class ThymeleafController {

	@GetMapping(path = "/thymeleaf-inputPage")
	public String thymeleafIn(Model model) { 
		User user = new User();
		model.addAttribute("userInput", user);
		return "thymeleaf-inputPage";
	}
	
	@PostMapping(path = "/thymeleaf-outputPage")
	public String thymeleafOut(@ModelAttribute("userInput") User user, Model model) {
		model.addAttribute("userOutput", user);
		return "thymeleaf-outputPage";
	}
}

//Userクラスの設定
class User{

	private String name;
	private String age;

    //getter,setter省略
}
~~~
~~~thymeleaf-inputPage.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head> 
    <title>Thymeleaf test</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>入力画面です</h1> 
    <form th:action="@{/thymeleaf-outputPage}" method="post" th:object="${userInput}">
		<p>名前</p>
		<input type="text" th:field="*{name}"/>
		<p>年齢</p>
		<input type="text" th:field="*{age}"/>
		<input type="submit" value="出力画面へ"/>
	</form>
</body>
</html>
~~~
~~~thymeleaf-outputPage.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head> 
    <title>Thymeleaf test</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>出力画面です</h1> 
    <div th:object="${userOutput}">
    	<p>名前</p>
		<p th:text="*{name}"></p>
		<p>年齢</p>
		<p th:text="*{age}"></p>
	</div>
</body>
</html>
~~~

## 解説
### 入力画面にアクセス
/thymeleaf-inputPageのページをURLに指定してアクセスするとコントローラーの`thymeleafInメソッド`が実行される。引数の`Model model`はビューに値を共有するためのインスタンスである。
~~~java:ThymeleafController.javaのthymeleafInメソッド抜粋
	@GetMapping(path = "/thymeleaf-inputPage")
	public String thymeleafIn(Model model) { 
		User user = new User();
		model.addAttribute("userInput", user);
		return "thymeleaf-inputPage";
	}
~~~
Userクラスのフィールドには`name`,`age`がある。
ビューでuserを使うため`model.addAttribute("userInput", user);` で`model`に`userInput=user`を代入する。
`return "thymeleaf-inputPage";`で出力画面の`thymeleaf-inputPage.html`が表示される。
### 入力画面

入力画面(thymeleaf-inputPage.html)ではth:fieldでuserOutputの変数を使用しているので入力欄にはname,ageの値が表示されるが、画面を表示したタイミングではuserのフィールド（nameとage）は値が入っていないため、入力欄には何も表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569317/8e2c0af8-4565-c05e-c680-b1908f7d2d34.png)

### 値を入力してボタンを押す
ここでは名前に「テスト太郎」、年齢に「30」を入れてボタンを押した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569317/c7d22f67-1bdc-fa2d-c78b-6eeda71c8766.png)


### 出力画面へ
名前、年齢を入力して出力画面へボタンを押すと、入力内容はオブジェクトの変数に格納された状態でコントローラに渡される。
~~~java:ThymeleafController.javaのthymeleafOutメソッド抜粋
	@PostMapping(path = "/thymeleaf-outputPage")
	public String thymeleafOut(@ModelAttribute("userInput") User user, Model model) {
		model.addAttribute("userOutput", user);
		return "thymeleaf-outputPage";
	}
~~~
コントローラでは`@ModelAttribute("userInput") User user`のコードで入力画面から受け取った`userInput`をUserクラスの変数userに格納している。
`model.addAttribute("userOutput", user);`でmodelに`userOutput=user`を格納し、ビュー側でuserデータを使えるようにする。
`return "thymeleaf-outputPage";`で`thymeleaf-outputPage.html`の画面を表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569317/9eec3733-a45b-9197-c26d-2751d4a94dbc.png)

### 出力画面へ 補足
returnが返される直前の状態をデバッグ機能で確認すると次の状態になっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569317/05033302-38cc-e5d8-8a9a-f39a112e6e8c.png)
modelにはuserOutputとしてuserInputデータのage,nameが格納されていることが確認できるが、@ModelAttributeで指定した`userInput`がmodelに格納されている事も確認できる。
フォームデータをそのまま出力する事はないと思われるが、出力画面で`userInput`のオブジェクトも使用できる。

## まとめ
コントローラーのmodelにオブジェクトを格納すると、ビューのThymeleafを使ってmodelに入れたオブジェクトが使える。
ビューの<input>タグ内でth:field""にオブジェクトを指定すると、コントローラ側でそのオブジェクトが共有される。ビュー側でオブジェクトを使うには、メソッドの引数に`@ModelAttribute("オブジェクト名") オブジェクトの型 メソッド内で使うインスタンス名`を指定すればよい。

## 参考
コントローラのコードは次のページの「5.5.11 選択オブジェクトへの変数式」を参考にしました

https://kanda-it-school-kensyu.com/java-spring-contents/sb_ch05/sb_0505/