SpringBoot/Thymeleaf
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
[[SpringBoot]]
* Thymeleaf を使ったView層の開発 [#ee213c4b]
2021-04-05 中田 コントローラクラスのテンプレを追記
2020-06-21 中村
Thymeleafは,SpringBootで推奨されている''テンプレートエン...
サーバサイドで画面 (View層)を生成することができる.
REST-APIを呼び出して,JavaScriptで動的に画面を書き換える...
アプローチが異なることに注意.
- こちらはクライアントサイドで画面を生成するやり方
- VueやAngularもこちらのアプローチになる.
** テンプレートエンジンとは [#d5922d83]
アプリケーションは,あらかじめ画面のひな型となるHTML~
(''テンプレート'')を用意しておく.
テンプレートは,ところどころ穴あき(変数)のHTMLになって...
@ControllerがDTOとテンプレートを指定すれば,ThymeleafがDT...
フィールド値をテンプレートの変数に代入して穴埋めし,完全...
にレンダリングしてブラウザに返却する.
** Thymeleaf の概要 [#xe97162e]
&attachref(thymeleaf.png);
@Controllerオブジェクト(@RestControllerではない)が処理...
含んだDTOと画面のひな型となるHTMLテンプレートを指示すれば...
ThymeleafがDTOの値をテンプレートの指定された場所に組み込...
レンダリングする.
テンプレートは,Spring Boot プロジェクトのresources/templ...
の下に,Thymeleafの変数を埋め込んだHTML形式で保存する.
なお,Spring Boot プロジェクトは,変数を含まないHTML(静的...
ページ)を持つこともでき,その場合には,resources/static/ ...
保存する.
** 1. 準備 [#l42d9e14]
*** build.gradle に依存性を追加 [#v54a471d]
build.gradle のdependenciesに以下を追記.
implementation 'org.springframework.boot:spring-boot-sta...
[[SpringBoot/依存]]を参考にして,他のライブラリとの前後関...
** 2. 画面設計 [#e005334d]
*** 2.1 画面と画面遷移 [#m0ad9a4c]
コーディングする前に,まずは画面と画面遷移を大まかでよい...
ノート等にスケッチしておくとよいだろう.
画面
- どんな画面があるか?
- それぞれのユースケースごとに画面があるはず
画面遷移
- 画面間の遷移はどうなっているか?
画面遷移の処理の流れを,最初の図を参照しながら,確認しよう
&attachref(./thymeleaf.png,50%);
+ ユーザがブラウザ上のボタンを押す
+ ControllerにGETまたはPOSTが発行される
+ ControllerがServiceを経由してビジネスロジックを実行し,...
+ Controllerが結果をModelに属性としてセットする.addAttri...
+ Controllerがreturnでテンプレートを''文字列''で指定する...
+ Thymeleafがtemplatesの中からテンプレート''文字列.html''...
+ Thymeleafがhoge.htmlにModelの属性値を流しこみ完全なHTML...
+ ユーザのブラウザ上に画面が現れる
*** 2.2 例題:健康診断Webアプリ [#mcfa36c0]
健康診断アプリ([[ソフトウェア工学第4回課題:http://www27....
- エンティティは[[SpringBoot/JPA]]を参照のこと
*** 画面の例 [#k9142c95]
&attachref(screens.png);
*** 画面遷移の例 [#vf8a3232]
&attachref(transition.png);
- &color(red){赤字}; は画面に対応するURLパスを表す
- 画面間の遷移のラベルは,[ボタン・リンク押下] / [コント...
- redirect:/persons は,アクション終了後にリダイレクトを...
** 3. @Controller クラスの構成 [#mffd1943]
サーバサイドで画面を構成する場合,@RestController クラス...
@Controller クラスを定義する (両方あっても構わないが,URL...
重ならないように気を付けること)
PersonController.java
@Controller
public class PersonController {
@Autowired
PersonManager pm; //サービスクラス
(以降メソッド定義)
}
各メソッドの定義について,2.2の例題にそって説明する.
*** 3.1 受診者リストの表示 (GET /persons) [#td8773fc]
登録されているすべての受診者のデータを画面に表示する
+ Serviceに問い合わせて,全受診者のリストを取得し personL...
+ 画面モデルに,属性plistを定義し,personListを紐づける
+ テンプレート list.html を呼び出す.
@GetMapping("/persons")
public String showAllPersons(Model model) {
List<PersonDto> personList = pm.getAllPersons();
model.addAttribute("plist", personList);
return "list";
}
*** 3.2 登録フォームの表示 (GET /persons/register) [#pe4d...
登録フォームを表示する
+ 空のフォームオブジェクトPersonFormを作成する
+ 画面モデルに,属性PersonFormを定義し,オブジェクトを紐...
+ テンプレート register.html を呼び出す.
@GetMapping("/persons/register")
public String showPersonForm(Model model) {
model.addAttribute("PersonForm", new PersonForm());
return "register";
}
*** 3.3 受診者情報の登録 (POST /persons) [#a9e3d4cb]
受診者情報をフォームから受け付けてDBに追加する.その後,...
+ ページからPOSTされた属性と値のペアを,@ModelAttribute ...
+ @Vaidatedでバリデーションする
+ エンティティに変換して,登録サービスに渡す addPerson()
+ /personsにリダイレクトし,一覧ページを表示する
@PostMapping("/persons")
public String addPerson(@ModelAttribute @Validated Perso...
pm.addPerson(form.toEntity());
return "redirect:/persons";
}
*** 3.4 更新フォームの表示 (GET /persons/{number}/update)...
更新フォームを表示する
+ パス・パラメータnumberから番号がnumberの受診者pを検索する
+ 画面モデルに,属性PersonFormを定義し,pを紐づける
+ テンプレート update.html を呼び出す
@GetMapping("/persons/{number}/update")
public String showUpdateForm(@PathVariable Long number, ...
PersonDto p = pm.getPerson(number);
model.addAttribute("PersonForm", p);
return "update";
}
*** 3.5 受診者情報を更新する (POST /persons/{number}/upda...
画面で更新された受診者情報をフォームから受け付けてDBに追...
- 注意: 更新なのでPUTで呼び出したい所だが,htmlの<form>...
+ ページからPOSTされた属性と値のペアを,@ModelAttribute ...
+ @Vaidatedでバリデーションする
+ パスパラメータから,受診者番号numberを取得する
+ formをエンティティに変換して,受診者番号numberとともに...
+ /personsにリダイレクトし,一覧ページを表示する
@PostMapping("/persons/{number}/update")
public String updatePerson(@ModelAttribute @Validated Pe...
pm.updatePerson(number, form.toEntity());
return "redirect:/persons";
}
*** 3.6 受診者情報を削除する (GET /persons/{number}/delet...
受診者情報を削除する (確認ルーチンは省略している)
- 注意: 削除なのでDELETEで呼び出したい所だが,クリックで...
+ パスパラメータから,受診者情報numberを取得する
+ 削除サービスを呼び出す deletePerson
+ /personsにリダイレクトし,一覧ページを表示する
@GetMapping("/persons/{number}/delete")
public String deletePerson(@PathVariable Long number, Mo...
pm.deletePerson(number);
return "redirect:/persons";
}
** 4. HTMLテンプレートを構成する [#p57092b5]
*** 4.1 扉ページ (static/index.html) [#g69a446e]
何の変哲もない,普通のHTML.ボタンを押すとpersonsに移動(G...
<!DOCTYPE html>
<html lang="ja">
<head>
<title>健康診断Webアプリケーション</title>
<link rel="stylesheet" type="text/css" href="style.c...
<meta charset="UTF-8">
</head>
<body>
<h1>健康診断Webアプリケーション</h1>
<div class="title">
<img src="img/shinchou.png" width="250px">
<img src="img/taijuu.png" width="250px">
</div>
<div>
<input type="button" class="simple_square_btn5" ...
</div>
</body>
</html>
*** 4.2 受診者一覧 (templates/list.html) [#u81ade37]
Thymeleafのテンプレート.重要なポイントが含まれる
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>受診者一覧</title>
<link rel="stylesheet" type="text/css" th:href="@{/s...
</head>
<body>
<h1>受診者一覧</h1>
<input type="button" class="simple_square_btn5" th:o...
<input type="button" class="simple_square_btn5" th:o...
<table class="tablist">
<tr>
<th>No.</th>
<th>受診者氏名</th>
<th>生年月日</th>
<th>身長</th>
<th>体重</th>
<th>BMI</th>
<th>肥満度</th>
<th>コマンド</th>
</tr>
<tr th:each="p: ${plist}">
<td> [[${p.number}]] </td>
<td> [[${p.name}]] </td>
<td> [[${p.birthday}]] </td>
<td> [[${p.height}]] cm </td>
<td> [[${p.weight}]] kg </td>
<td> [[${#numbers.formatDecimal(p.bmi == nul...
<th:block th:switch="${p.obesity}">
<td th:case="'低体重'" style="background...
<td th:case="'普通体重'" style="backgrou...
<td th:case="'肥満 (1度)'" style="backgr...
<td th:case="'肥満 (2度)'" style="backgr...
<td th:case="'肥満 (3度)'" style="backgr...
<td th:case="'肥満 (4度)'" style="backgr...
<td th:case="*">[[${p.obesity}]]</td>
</th:block>
<td>
<a th:href=@{/persons/{num}/update(num=$...
<a th:href=@{/persons/{num}/delete(num=$...
</td>
</tr>
</table>
</body>
*** 解説 [#x1a6b6bd]
- ''<html>タグ:'' xmlns:th="http://www.thymeleaf.org" の...
-- Thymeleafの名前空間 th を定義する.これは必須のおまじ...
- ''th: がついている部分''は,Thymeleafが動的に書き換える...
-- (テンプレート) th:属性名 = "[[Thymeleaf式:https://www....
-- (実行時) 属性名 = [[Thymeleaf式:https://www.thymeleaf....
- ''変数式:'' Contollerから渡された変数の値を取り出す
-- <td th:text="${p.name}"></td> と書いておくと (pはCont...
-- <td>仲村 匡日出</td> と展開される.
- ''インライン式:'' 式をhtmlの中に直接書く
-- <td> [ [${p.name}] ]</td>
- ''リンク式:'' リンクのコンテキストパスをあんじょうやっ...
-- パス・パラメータ{}は()の中で指定する(C言語のprintf()的...
-- <a th:href="@{/persons/{num}/update(num=${p.number})}"...
-- <a href="/person/1/update">編集</a> と展開される
- ''リテラル置換'': |・・・| で囲まれた部分を文字列に展開...
- ''三項演算子式:'' 条件に応じて,値を切り替える
-- 式1 ? 値1: 値2
-- 式1がtrueの場合,値1に評価される.falseの場合,値2に評...
- ''ブロック''
-- <th:block> </th:block>でテンプレート内のブロックを定義...
-- テンプレートを構造化する用途に使う→(繰り返し,分岐,...
-- 実行時には消える
- ''繰り返し'' : リストから一つずつ取り出して表示
-- <タグ th:each="p: ${plist}"> ... </タグ> と書いておく...
-- plistから要素p0,p1,...,pnを一つずつ取り出して,
-- <タグ> p_0を展開した内容 </タグ> <タグ> p_1を展開した...
- ''条件'': 式が成立した時だけ表示
-- <タグ th:if="式">式がtrueのときだけこの内容が出ます</...
-- <タグ th:unless="式">式がfalseのときだけこの内容が出ま...
- ''スイッチ'': 式の値によって分岐
-- <th:block th:switch="式1">
--- <タグ th:case="式2">式1==式2の時だけこの内容が出ます...
** 4.3 受診者登録 (templates/register.html) [#ma1e1871]
登録フォーム.
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>受診者情報登録</title>
<link rel="stylesheet" type="text/css" th:href="@{/s...
</head>
<body>
<h1>受診者情報登録</h1>
<form role="form" th:action="@{/persons}" th:object=...
<table class="tabform large">
<tr>
<td><label for="number">No: </label></td>
<td><span th:text="${number}"></span></td>
</tr>
<tr>
<td><label for="name">氏名: </label></td>
<td><input class="large" type="text" req...
</tr>
<tr>
<td><label for="birthday">生年月日:</la...
<td><input class="large" type="text" req...
</tr>
<tr>
<td><label for="height">身長:</label></...
<td><input class="large" type="number" r...
</tr>
<tr>
<td><label for="weight">体重:</label></...
<td><input class="large" type="number" r...
</tr>
<tr>
<td colspan="2">
<input type="button" class="large si...
<input type="submit" class="large si...
</td>
</tr>
</table>
</form>
</body>
</html>
*** 解説 [#a467ef52]
- Controllerから空のフォームを''PersonForm''という属性名...
- <form>の中のth:object="${PersonForm}" で,このフォーム...
- <input>の中の"*{name}"は,現在参照しているオブジェクト...
-- "${PersonForm.name}" と同じ意味
- <form ... th:object="${フォーム変数}"> ~<input ... th:...
-- <input>の中に,id, name, valueを勝手に展開してくれる
-- [[フォームバインディング:https://casual-tech-note.hate...
Thymeleaf でフォームを書く時の鉄板らしい
- 最下部の<input type="submit" ..> ボタンを押すと入力が<f...
-- メソッドはPOST /persons
-- 送信されるデータは,各inputのnameとvalueのペア
- 3.3 のコントローラに渡され,登録後,一覧にリダイレクト...
** 4.4 受診者更新 (templates/update.html) [#oa7db494]
4.3とほぼ同じなので割愛
** 完全なコード [#y2d30352]
- GitLab: Medical CheckApp
-- http://teamserv.cs.kobe-u.ac.jp:443/masa-n/medicalchec...
** 参考文献 [#eb8d78c6]
- Thymeleaf チュートリアル
-- https://www.thymeleaf.org/doc/tutorials/3.0/usingthyme...
- Spring Boot で Thymeleaf 使い方メモ
-- https://qiita.com/opengl-8080/items/eb3bf3b5301bae398cc2
- [[Spring Boot 2実践入門:簡単なWEBアプリを一から作成チ...
- 【Spring Boot】ModelクラスとModel And Viewクラス
-- https://pointsandlines.jp/java/model-and-view
- Thymeleafを使用した入力フォームのサンプルコード
-- https://qiita.com/rubytomato@github/items/387d46ea34eb...
** コントローラクラステンプレ(by中田) [#ld3fde9d]
@Controller
class MyController {
@GetMapping("/page")
public String getSomething(
Model model,
RedirectAttributes attributes,
@ModelAttribute
@Validated
MyForm form,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
attributes.addFlashAttribute("isError", true);
attributes.addFlashAttribute("arg", "hoge");
return "redirect:/";
}
model.addAttribute("arg", "fuga");
return "next";
}
}
- @Controller
-- ThymeleafのControllerクラスにつけるアノテーション
-- コンポーネントスキャンの対象となる
- Model
-- Viewで使える変数
-- addAttribute : Viewで使える変数を設定する
- RedirectAttributes
-- リダイレクトに使う
-- addAttribute : リダイレクト先に渡す引数の設定
-- addFlashAttribute : リダイレクト先でmodel.addAttribute...
- @ModelAttribute
-- リクエストボディの内容を受け取る
- @Validated
-- バリデーションを有効化する
- BindingResult
-- 直前の引数のバリデーション結果を格納する
- return
-- "page"だと、page.htmlを返す
-- redirect : 指定したURLに移動して読み込み直す
終了行:
[[SpringBoot]]
* Thymeleaf を使ったView層の開発 [#ee213c4b]
2021-04-05 中田 コントローラクラスのテンプレを追記
2020-06-21 中村
Thymeleafは,SpringBootで推奨されている''テンプレートエン...
サーバサイドで画面 (View層)を生成することができる.
REST-APIを呼び出して,JavaScriptで動的に画面を書き換える...
アプローチが異なることに注意.
- こちらはクライアントサイドで画面を生成するやり方
- VueやAngularもこちらのアプローチになる.
** テンプレートエンジンとは [#d5922d83]
アプリケーションは,あらかじめ画面のひな型となるHTML~
(''テンプレート'')を用意しておく.
テンプレートは,ところどころ穴あき(変数)のHTMLになって...
@ControllerがDTOとテンプレートを指定すれば,ThymeleafがDT...
フィールド値をテンプレートの変数に代入して穴埋めし,完全...
にレンダリングしてブラウザに返却する.
** Thymeleaf の概要 [#xe97162e]
&attachref(thymeleaf.png);
@Controllerオブジェクト(@RestControllerではない)が処理...
含んだDTOと画面のひな型となるHTMLテンプレートを指示すれば...
ThymeleafがDTOの値をテンプレートの指定された場所に組み込...
レンダリングする.
テンプレートは,Spring Boot プロジェクトのresources/templ...
の下に,Thymeleafの変数を埋め込んだHTML形式で保存する.
なお,Spring Boot プロジェクトは,変数を含まないHTML(静的...
ページ)を持つこともでき,その場合には,resources/static/ ...
保存する.
** 1. 準備 [#l42d9e14]
*** build.gradle に依存性を追加 [#v54a471d]
build.gradle のdependenciesに以下を追記.
implementation 'org.springframework.boot:spring-boot-sta...
[[SpringBoot/依存]]を参考にして,他のライブラリとの前後関...
** 2. 画面設計 [#e005334d]
*** 2.1 画面と画面遷移 [#m0ad9a4c]
コーディングする前に,まずは画面と画面遷移を大まかでよい...
ノート等にスケッチしておくとよいだろう.
画面
- どんな画面があるか?
- それぞれのユースケースごとに画面があるはず
画面遷移
- 画面間の遷移はどうなっているか?
画面遷移の処理の流れを,最初の図を参照しながら,確認しよう
&attachref(./thymeleaf.png,50%);
+ ユーザがブラウザ上のボタンを押す
+ ControllerにGETまたはPOSTが発行される
+ ControllerがServiceを経由してビジネスロジックを実行し,...
+ Controllerが結果をModelに属性としてセットする.addAttri...
+ Controllerがreturnでテンプレートを''文字列''で指定する...
+ Thymeleafがtemplatesの中からテンプレート''文字列.html''...
+ Thymeleafがhoge.htmlにModelの属性値を流しこみ完全なHTML...
+ ユーザのブラウザ上に画面が現れる
*** 2.2 例題:健康診断Webアプリ [#mcfa36c0]
健康診断アプリ([[ソフトウェア工学第4回課題:http://www27....
- エンティティは[[SpringBoot/JPA]]を参照のこと
*** 画面の例 [#k9142c95]
&attachref(screens.png);
*** 画面遷移の例 [#vf8a3232]
&attachref(transition.png);
- &color(red){赤字}; は画面に対応するURLパスを表す
- 画面間の遷移のラベルは,[ボタン・リンク押下] / [コント...
- redirect:/persons は,アクション終了後にリダイレクトを...
** 3. @Controller クラスの構成 [#mffd1943]
サーバサイドで画面を構成する場合,@RestController クラス...
@Controller クラスを定義する (両方あっても構わないが,URL...
重ならないように気を付けること)
PersonController.java
@Controller
public class PersonController {
@Autowired
PersonManager pm; //サービスクラス
(以降メソッド定義)
}
各メソッドの定義について,2.2の例題にそって説明する.
*** 3.1 受診者リストの表示 (GET /persons) [#td8773fc]
登録されているすべての受診者のデータを画面に表示する
+ Serviceに問い合わせて,全受診者のリストを取得し personL...
+ 画面モデルに,属性plistを定義し,personListを紐づける
+ テンプレート list.html を呼び出す.
@GetMapping("/persons")
public String showAllPersons(Model model) {
List<PersonDto> personList = pm.getAllPersons();
model.addAttribute("plist", personList);
return "list";
}
*** 3.2 登録フォームの表示 (GET /persons/register) [#pe4d...
登録フォームを表示する
+ 空のフォームオブジェクトPersonFormを作成する
+ 画面モデルに,属性PersonFormを定義し,オブジェクトを紐...
+ テンプレート register.html を呼び出す.
@GetMapping("/persons/register")
public String showPersonForm(Model model) {
model.addAttribute("PersonForm", new PersonForm());
return "register";
}
*** 3.3 受診者情報の登録 (POST /persons) [#a9e3d4cb]
受診者情報をフォームから受け付けてDBに追加する.その後,...
+ ページからPOSTされた属性と値のペアを,@ModelAttribute ...
+ @Vaidatedでバリデーションする
+ エンティティに変換して,登録サービスに渡す addPerson()
+ /personsにリダイレクトし,一覧ページを表示する
@PostMapping("/persons")
public String addPerson(@ModelAttribute @Validated Perso...
pm.addPerson(form.toEntity());
return "redirect:/persons";
}
*** 3.4 更新フォームの表示 (GET /persons/{number}/update)...
更新フォームを表示する
+ パス・パラメータnumberから番号がnumberの受診者pを検索する
+ 画面モデルに,属性PersonFormを定義し,pを紐づける
+ テンプレート update.html を呼び出す
@GetMapping("/persons/{number}/update")
public String showUpdateForm(@PathVariable Long number, ...
PersonDto p = pm.getPerson(number);
model.addAttribute("PersonForm", p);
return "update";
}
*** 3.5 受診者情報を更新する (POST /persons/{number}/upda...
画面で更新された受診者情報をフォームから受け付けてDBに追...
- 注意: 更新なのでPUTで呼び出したい所だが,htmlの<form>...
+ ページからPOSTされた属性と値のペアを,@ModelAttribute ...
+ @Vaidatedでバリデーションする
+ パスパラメータから,受診者番号numberを取得する
+ formをエンティティに変換して,受診者番号numberとともに...
+ /personsにリダイレクトし,一覧ページを表示する
@PostMapping("/persons/{number}/update")
public String updatePerson(@ModelAttribute @Validated Pe...
pm.updatePerson(number, form.toEntity());
return "redirect:/persons";
}
*** 3.6 受診者情報を削除する (GET /persons/{number}/delet...
受診者情報を削除する (確認ルーチンは省略している)
- 注意: 削除なのでDELETEで呼び出したい所だが,クリックで...
+ パスパラメータから,受診者情報numberを取得する
+ 削除サービスを呼び出す deletePerson
+ /personsにリダイレクトし,一覧ページを表示する
@GetMapping("/persons/{number}/delete")
public String deletePerson(@PathVariable Long number, Mo...
pm.deletePerson(number);
return "redirect:/persons";
}
** 4. HTMLテンプレートを構成する [#p57092b5]
*** 4.1 扉ページ (static/index.html) [#g69a446e]
何の変哲もない,普通のHTML.ボタンを押すとpersonsに移動(G...
<!DOCTYPE html>
<html lang="ja">
<head>
<title>健康診断Webアプリケーション</title>
<link rel="stylesheet" type="text/css" href="style.c...
<meta charset="UTF-8">
</head>
<body>
<h1>健康診断Webアプリケーション</h1>
<div class="title">
<img src="img/shinchou.png" width="250px">
<img src="img/taijuu.png" width="250px">
</div>
<div>
<input type="button" class="simple_square_btn5" ...
</div>
</body>
</html>
*** 4.2 受診者一覧 (templates/list.html) [#u81ade37]
Thymeleafのテンプレート.重要なポイントが含まれる
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>受診者一覧</title>
<link rel="stylesheet" type="text/css" th:href="@{/s...
</head>
<body>
<h1>受診者一覧</h1>
<input type="button" class="simple_square_btn5" th:o...
<input type="button" class="simple_square_btn5" th:o...
<table class="tablist">
<tr>
<th>No.</th>
<th>受診者氏名</th>
<th>生年月日</th>
<th>身長</th>
<th>体重</th>
<th>BMI</th>
<th>肥満度</th>
<th>コマンド</th>
</tr>
<tr th:each="p: ${plist}">
<td> [[${p.number}]] </td>
<td> [[${p.name}]] </td>
<td> [[${p.birthday}]] </td>
<td> [[${p.height}]] cm </td>
<td> [[${p.weight}]] kg </td>
<td> [[${#numbers.formatDecimal(p.bmi == nul...
<th:block th:switch="${p.obesity}">
<td th:case="'低体重'" style="background...
<td th:case="'普通体重'" style="backgrou...
<td th:case="'肥満 (1度)'" style="backgr...
<td th:case="'肥満 (2度)'" style="backgr...
<td th:case="'肥満 (3度)'" style="backgr...
<td th:case="'肥満 (4度)'" style="backgr...
<td th:case="*">[[${p.obesity}]]</td>
</th:block>
<td>
<a th:href=@{/persons/{num}/update(num=$...
<a th:href=@{/persons/{num}/delete(num=$...
</td>
</tr>
</table>
</body>
*** 解説 [#x1a6b6bd]
- ''<html>タグ:'' xmlns:th="http://www.thymeleaf.org" の...
-- Thymeleafの名前空間 th を定義する.これは必須のおまじ...
- ''th: がついている部分''は,Thymeleafが動的に書き換える...
-- (テンプレート) th:属性名 = "[[Thymeleaf式:https://www....
-- (実行時) 属性名 = [[Thymeleaf式:https://www.thymeleaf....
- ''変数式:'' Contollerから渡された変数の値を取り出す
-- <td th:text="${p.name}"></td> と書いておくと (pはCont...
-- <td>仲村 匡日出</td> と展開される.
- ''インライン式:'' 式をhtmlの中に直接書く
-- <td> [ [${p.name}] ]</td>
- ''リンク式:'' リンクのコンテキストパスをあんじょうやっ...
-- パス・パラメータ{}は()の中で指定する(C言語のprintf()的...
-- <a th:href="@{/persons/{num}/update(num=${p.number})}"...
-- <a href="/person/1/update">編集</a> と展開される
- ''リテラル置換'': |・・・| で囲まれた部分を文字列に展開...
- ''三項演算子式:'' 条件に応じて,値を切り替える
-- 式1 ? 値1: 値2
-- 式1がtrueの場合,値1に評価される.falseの場合,値2に評...
- ''ブロック''
-- <th:block> </th:block>でテンプレート内のブロックを定義...
-- テンプレートを構造化する用途に使う→(繰り返し,分岐,...
-- 実行時には消える
- ''繰り返し'' : リストから一つずつ取り出して表示
-- <タグ th:each="p: ${plist}"> ... </タグ> と書いておく...
-- plistから要素p0,p1,...,pnを一つずつ取り出して,
-- <タグ> p_0を展開した内容 </タグ> <タグ> p_1を展開した...
- ''条件'': 式が成立した時だけ表示
-- <タグ th:if="式">式がtrueのときだけこの内容が出ます</...
-- <タグ th:unless="式">式がfalseのときだけこの内容が出ま...
- ''スイッチ'': 式の値によって分岐
-- <th:block th:switch="式1">
--- <タグ th:case="式2">式1==式2の時だけこの内容が出ます...
** 4.3 受診者登録 (templates/register.html) [#ma1e1871]
登録フォーム.
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>受診者情報登録</title>
<link rel="stylesheet" type="text/css" th:href="@{/s...
</head>
<body>
<h1>受診者情報登録</h1>
<form role="form" th:action="@{/persons}" th:object=...
<table class="tabform large">
<tr>
<td><label for="number">No: </label></td>
<td><span th:text="${number}"></span></td>
</tr>
<tr>
<td><label for="name">氏名: </label></td>
<td><input class="large" type="text" req...
</tr>
<tr>
<td><label for="birthday">生年月日:</la...
<td><input class="large" type="text" req...
</tr>
<tr>
<td><label for="height">身長:</label></...
<td><input class="large" type="number" r...
</tr>
<tr>
<td><label for="weight">体重:</label></...
<td><input class="large" type="number" r...
</tr>
<tr>
<td colspan="2">
<input type="button" class="large si...
<input type="submit" class="large si...
</td>
</tr>
</table>
</form>
</body>
</html>
*** 解説 [#a467ef52]
- Controllerから空のフォームを''PersonForm''という属性名...
- <form>の中のth:object="${PersonForm}" で,このフォーム...
- <input>の中の"*{name}"は,現在参照しているオブジェクト...
-- "${PersonForm.name}" と同じ意味
- <form ... th:object="${フォーム変数}"> ~<input ... th:...
-- <input>の中に,id, name, valueを勝手に展開してくれる
-- [[フォームバインディング:https://casual-tech-note.hate...
Thymeleaf でフォームを書く時の鉄板らしい
- 最下部の<input type="submit" ..> ボタンを押すと入力が<f...
-- メソッドはPOST /persons
-- 送信されるデータは,各inputのnameとvalueのペア
- 3.3 のコントローラに渡され,登録後,一覧にリダイレクト...
** 4.4 受診者更新 (templates/update.html) [#oa7db494]
4.3とほぼ同じなので割愛
** 完全なコード [#y2d30352]
- GitLab: Medical CheckApp
-- http://teamserv.cs.kobe-u.ac.jp:443/masa-n/medicalchec...
** 参考文献 [#eb8d78c6]
- Thymeleaf チュートリアル
-- https://www.thymeleaf.org/doc/tutorials/3.0/usingthyme...
- Spring Boot で Thymeleaf 使い方メモ
-- https://qiita.com/opengl-8080/items/eb3bf3b5301bae398cc2
- [[Spring Boot 2実践入門:簡単なWEBアプリを一から作成チ...
- 【Spring Boot】ModelクラスとModel And Viewクラス
-- https://pointsandlines.jp/java/model-and-view
- Thymeleafを使用した入力フォームのサンプルコード
-- https://qiita.com/rubytomato@github/items/387d46ea34eb...
** コントローラクラステンプレ(by中田) [#ld3fde9d]
@Controller
class MyController {
@GetMapping("/page")
public String getSomething(
Model model,
RedirectAttributes attributes,
@ModelAttribute
@Validated
MyForm form,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
attributes.addFlashAttribute("isError", true);
attributes.addFlashAttribute("arg", "hoge");
return "redirect:/";
}
model.addAttribute("arg", "fuga");
return "next";
}
}
- @Controller
-- ThymeleafのControllerクラスにつけるアノテーション
-- コンポーネントスキャンの対象となる
- Model
-- Viewで使える変数
-- addAttribute : Viewで使える変数を設定する
- RedirectAttributes
-- リダイレクトに使う
-- addAttribute : リダイレクト先に渡す引数の設定
-- addFlashAttribute : リダイレクト先でmodel.addAttribute...
- @ModelAttribute
-- リクエストボディの内容を受け取る
- @Validated
-- バリデーションを有効化する
- BindingResult
-- 直前の引数のバリデーション結果を格納する
- return
-- "page"だと、page.htmlを返す
-- redirect : 指定したURLに移動して読み込み直す
ページ名: