たなかのJava日記

どんなことをやったか(学んだか)、どこで詰まったか(わからなかったか)、どこで工夫したかの記録です。Dayで始まる記事は1日遅れで更新されることが多いです。

【Spring Boot】HTMLとJavaを分けて構成する②

前回まででThymeleafを利用する準備が整いました。
次にWebページの静的部分を構成するHTMLテンプレートを作成します。


HTMLテンプレート作成する場所は、
プロジェクトのsrc/resources/templatesディレクトリ以下です。
今回はhello.htmlというファイルで作成します。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <h1>Hello</h1>
    It works<br>
    現在時刻は<span th:text="${time}"></span>です。
</body>
</html>


通常のHTMLと異なる部分があります。
まず、htmlタグの宣言部分です。

<html xmlns:th="http://www.thymeleaf.org">

ここに付けられているxmlns:thの属性がThymeleafのテンプレートであることを示す宣言になります。
もっと平易な言葉で説明すると、これでThymeleafが使えるようになるということです。

このツールを使用することによって、
個別のファイルで作成されたHTMLテンプレートファイルとJavaプログラムがHTTPリクエストを受け取ると、
HTMLファイルにJavaのプログラムで生成されたデータを埋め込んでレスポンスとして返すことができます。


もう一つ通常のHTMLと大きく異なる箇所があります。本文の中にあるspanタグの部分です。

<span th:text="${time}"></span>


ここはサーバー上の現在時刻を示す部分です。
時刻はリアルタイムで表示したいので、あらかじめHTMLに書いておくことができません。
このページにアクセスし表示されるときに、時刻を取得するようにしたいです。
そこで、HTTPレスポンスを返す段階でテンプレートエンジン(Thymeleaf)によって動的に中身を変える仕組みを使います。
今回の場合、th:textと書かれている部分がThymeleafによって処理される箇所になります。
具体的な処理の内容は、spanタグの中身がth:text属性の値として指定されている文字列に変わります。
属性の中では変数を使用することができ、${}を使って表現します。
今回は${time}としていますが、spanタグの中身がtime変数の値になるということです。
time変数には、Javaのプログラムから値を設定することができるようになっています。


これでhello.htmlは、HTMLとしてJavaから分けることができました。
次にHomeControllerクラスのhelloメソッドで、今作成したhello.htmlを使うようにJavaプログラムを書き換えます。
書き換える理由としては、以下の流れで言うとJavaで現在時刻の取得する処理を行った結果を、
hello.htmlのtime変数に埋め込みたいからです。


HTTPリクエストを受け取る

Javaで現在時刻の取得する処理を行う

処理を行った結果(現在時刻)をHTMLの変数へ指定して渡す

HTMLでデータ(現在時刻)を受け取ったら指定された箇所(time変数)へ埋め込む

埋め込んだ結果をHTMLレスポンスとして返す

結果がWebブラウザに表示される

@Controller
public class HomeController {
    @RequestMapping(value="/hello")
    String hello(Model model) {
        model.addAttribute("time", LocalDateTime.now());
        return "hello";
    }
}

繰り返しになりますが、ここで行っていることは、
Javaで現在時刻の取得する処理を行い、処理の結果(現在時刻)をHTMLへ渡すだけになります。
また、今回はビューを構成するHTMLはコントローラ自身ではなくテンプレートエンジンが作成してくれます。
なので、JavaとHTMLを別々にしているということはここにHTMLは書きませんし、
このエンドポイントのメソッドではHTTPレスポンスの本体そのものは返しません。
@ResponseBodyアノテーションも付けません。

返すのは、対応するビュー名の文字列になります。
対応するビュー名というのは、このJavaのhelloメソッドの処理結果はどこのHTMLに埋め込むのか、
そのHTMLの名前になります。
注意点としては、ビュー名は設定ファイルなどで別途指定していない場合には、
HTMLのテンプレートファイルから拡張子を除いたものになります。
今回のhelloメソッド場合、hello.htmlを使うので「hello」をビュー名として返します。
その仕組み(処理の結果(現在時刻)をHTMLへ渡すこと)がhelloメソッド内になります。


String hello(Model model)


引数として、org.springframework.ui.Modelクラスのオブジェクトを受け取ります。
ModelクラスはJavaプログラムとHTMLテンプレートの間で値を受け渡す役割を担います。


model.addAttribute("time", LocalDateTime.now());


引数に渡されたModelオブジェクトに対しては、addAttributeメソッドを使って属性を設定できます。
属性はキーと値の組み合わせになっていて、キーはHTMLテンプレート側で使用している変数になります。

まとめると、今回はhello.htmlに渡す属性として、
キーに"time"を、
値に現在時刻を設定しています。
こうすることで、hello.htmlの${time}の部分が渡された現在時刻に置き換えられる仕組みになっています。


この状態でプロジェクトを再実行し、ブラウザでアクセスします。

http://localhost:8888/hello
※ポート番号は自分で指定した値を使用する

問題なく表示されていれば成功です。