きり丸アドベントカレンダー2020の6記事目です。
始めに宣言しておくと、この辺から「やはりIntelliJ IDEAいいなぁ…」みたいに思うことが多くなってきます。しょうがないとはいえ、GitpodやVS Codeはライブラリのimport機能が貧弱です。
コーディング中に引っかかった点は、ちゃんと明記しますが、気を付けて写経してください。
Thymeleafとは
Spring Bootが推奨しているテンプレートエンジンです。ただ、現在も推奨しているのかは、どこのリファレンスを見ればいいのかわかりませんでした。
特徴としてはJavaで画面といえばJSPだったのが、HTMLを使用できることにより、Javaを起動していない状態でもデザインを確認できることができます。つまり、デザイナーが作ったものをほとんど修正を加えずに開発者が使用できます。
と、いいつつ個人的にはあまり推奨はしません…。
理由としては、2点あります。
- テンプレートを分割できるせいで、HTML単体ではCSSが読み込まれなくなり、デザイン確認は難しい
- サーバからHtmlにパラメータを渡した際に、不備があった時の原因把握が難しい
個人的にThymeleafにいい思い出がありません。
ただし、次の2点からアドベントカレンダーにはThymeleafを採用しました。
- 画面を「React.js」や「Vue.js」でSPAとして作成するのは難易度が高い
- JSPよりはThymeleafがいい
ゴール
- 画面を表示する
- Javaから渡した値が画面に表示されている
手順
build.gradleにThymeleafを追加する
build.gradle
に依存関係を追加する。
dependencies {
compile 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
ThymeleafのモードをHTMLにする
ThymeleafのモードをHTMLにしてください。
デフォルトだとHTML5モードで動いてしまうらしいので、意図的にHTMLモードを設定する必要があります。
spring: thymeleaf: mode: HTML
HTMLファイルを格納する
src/main/resources
のディレクトリの下に、templates
ディレクトリを作成します。
src/main/resources/templates
のディレクトリに配備したファイルが、公開対象のファイルとなります。
今回は、index.html
ファイルを格納します。
${message}と${todos}等は、Java側から設定するパラメータを表示しています。
<!doctype html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>TODOアプリ</title> </head> <body> <h1>TODOアプリ</h1> <h1 th:text="${message}"></h1> <table border="1"> <tr> <th>ID</th> <th>USER_ID</th> </tr> <tr th:each="todo : ${todos}"> <td th:text="${todo.id}"></td> <td th:text="${todo.userId}"></td> </tr> </table> </body> </html>
Javaでindex.htmlを表示するようにする
@Controller
と@GetMapping
を付与したJavaファイルを作成します。ファイル自体は基本的にどこにおいても大丈夫です。
今回は、src/main/java/com/example/demo/controller
ディレクトリにIndexController.java
を作成しています。
ちなみに、この@XXX
をアノテーションと言います。
// 自動でimportされていなければ、手入力してください。 import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller // HTMLとのやり取りをするためのアノテーション public class IndexController { @GetMapping("/") // パラメータでURLを指定します。 public String index() { return "index"; // src/main/resources/templates配下のindex.htmlにマッピングします } }
起動確認
一旦、ここで起動確認してください。
ここまでうまく作成できていれば、今まではエラー画面だったのが、今回作ったhtmlファイルを表示できます。
./gradlew bootRun
または、git push
してHerokuを確認する。
JavaからHTMLにパラメータを渡す(単純なString)
パラメータにModelを追加してください。このModelに値を設定すると、Springがいい感じにマッピングしてくれて画面に表示されます。
今回は、index.htmlに${message}という項目を作成しました。Javaもこのmessageに対して値を設定すると画面に表示されます。
@Controller public class IndexController { @GetMapping("/") public String index(Model model) { // Modelを追加 model.addAttribute("message", "きり丸さんこんにちは"); // message return "index"; } }
JavaからHTMLにパラメータを渡す(DTO)
TODOアプリですので、TODOに関するクラスを作成します。
まだ何が必要かわからないので、id
とuserId
の項目を持たせるようにしましょう。また、lombokという便利なライブラリがあるので、@Data
と@Builder
をクラスに付与します。
クラス名はなんでもいいですが、私はControllerが使うクラスはDto
と名付けることが多いです。DTOはData transfer Objectの略称で、データ転送用のクラスです。
@Data // lombokの便利なもの(setter, getterを自動作成してくれる) @Builder // lombokのBuilderパターンを作れるようになります。 public class TodoDto { int id; String userId; }
また、TODOアプリですので、複数のTODOを渡したほうがいいでしょう。Thymeleaf側にも、複数のTODOデータをもらう前提で作りました。
挙動としてはJavaから受け取った${todos}
を変数todo
に設定し、変数に含まれているid
とuserId
を取得しています。
<tr th:each="todo : ${todos}"> <td th:text="${todo.id}"></td> <td th:text="${todo.userId}"></td> </tr>
Javaは単純にList<TodoDto>
をmodelに設定しています。
import java.util.List; @Controller public class IndexController { @GetMapping("/") public String index(Model model) { // Listで複数のTODOを用意する List<TodoDto> todos = List.of(TodoDto.builder().id(1).userId("kirimaru").build(), TodoDto.builder().id(2).userId("kirimaru").build()); model.addAttribute("message", "きり丸さんこんにちは"); model.addAttribute("todos", todos); // todosを設定する。 return "index"; } }
うまく設定できていれば、画面がこのように表示されています。
ついでにうまくいかないパターンを試す
Thymeleaf側はgetterを準備していないとパラメータを取得できません。
今回はTodoDto
クラスに@Data
を付与していたので、うまく動きました。
この@Data
をコメントにして、起動確認をしてみましょう。うまく動かないことが分かります。エラーメッセージからはtodo.id
が悪いことは分かるのですが…。Javaが悪いのか、HTMLが悪いのかを切り分けられないので、私にThymeleafは難しいです。
ソースコード
アドベントカレンダー6日目。
github.com
終わりに
まだおおがかりではないものの、JavaとHTMLを接続できました。ただ、今回のはJava -> HTMLの一方通行のみです。保存していたデータを表示することしかできません。
画面で編集したデータを更新するためには、HTML -> Javaの接続ができなければなりません。
アドベントカレンダー7日目はHTML -> Javaの接続を行います。
ぜひお楽しみに!
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。
参考記事
Thymeleaf公式ドキュメント www.thymeleaf.org
類似記事
きり丸アドベントカレンダー2020 adventar.org
きり丸のHerokuページ
https://kirimaru-todoapp.herokuapp.com/
7日目のアドベントカレンダーの記事 https://nainaistar.hatenablog.com/entry/2020/12/07/083000nainaistar.hatenablog.com