はじめに
こんにちは!
macでSTSの環境構築を行って、Spring BootでHelloWorldしていた者です。
今回は簡単なエコーアプリケーションを作成してみました。
画面遷移図っぽくすると、以下のようになります。
↓「送信」押下 ↑「お返事bot TOP」押下
前回、前々回同様、Spring徹底入門を参考に進めました。
本にはSpring MVCでのエコーアプリケーションの作り方と、SpringBootでのHelloWorldのコードは載っているのですが、Spring Bootでのエコーアプリケーションの方法はなかったので、なんとか混ぜ合わせながら作りました。
本当はバリデートとかテストコードとかもチャカチャカ実装するつもりだったのですが…Viewで使っているThymeleafに馴染みがなく(今までJSPを使っていましたが、非推奨らしい…!)、概念と書き方に慣れるのにちょっと時間がかかりました!ので、バリデートとか一切ない、ただのピュアなエコーアプリケーションです!
Thymeleaf?テンプレートエンジン?何それ?な人が読むとちょっと得するかも!な内容となっています。
使用環境とバージョン
- macOS Catalina
- jdk14.0.1
- JUnit5
- Maven 3.6.3_1
- STS 4.6.1
- Spring Boot 2.3.1
- spring-boot-starter-thymeleaf-2.3.1
Spring Initializrでプロジェクトの雛形を作る
前回同様Spring Initializrでプロジェクトの雛形を作成します。
使い方自体は前回と変わらないので、相違点だけ紹介します。
(左上から)
-
Spring Bootのバージョン
前回は2.3.0があったのですが、今回なくなっていたので2.3.1を使用しました1。 -
Project Metadata
前回はデフォルトのdemoのままで行いましたが、同名ファイルだと混ざるのでformに変更しました2。 -
Dependencies【重要!】
前回は何も指定しませんでしたが、今回はThymeleafを使用するため、ADD DEPENDENCIESからThymeleafを選択しました。(もちろん後からpom.xmlを書き換えればなんとかなりますが…)
ファイル構成
前回はメインメソッドとコントローラーを同じクラスDemoApplication.java
にしていましたが、今回はメインメソッドはEchoApplication.java
に、コントローラーはEchoController.java
に分けて作成しました。ただ、2つのHTMLそれぞれにコントローラーを作るほどでもなかったので、コントローラー1つで2つのページを担当しています。
そのほか、EchoFormクラスは画面に入力された値(今回はお返事botなので入力する値は名前)を受け取るクラスです。index.html
がお返事bot TOPページ、echo.html
は名前「もょもと」が送信されたあとで「Hello もょもと」とお返事していたページです3。
①コントローラーの作成
EchoApplication.java
はテンプレートそのままですので、割愛します。
EchoController.java
は以下のようになりました。
package com.example.form;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping
public class EchoController {
@ModelAttribute
public EchoForm setUpEchoForm() {
EchoForm form = new EchoForm();
return form;
}
@RequestMapping
public String index(Model model) {
return "index";
}
@RequestMapping(value = "echo", method = RequestMethod.POST)
public String echo(EchoForm form, Model model) {
model.addAttribute("name", form.getName());
return "echo";
}
}
(早くもformというパッケージ名を後悔し始めている、echoだったな)
setUpEchoForm
メソッドについている@ModelAttribute
は、そのメソッドの戻り値を自動でModelに追加するためのアノテーションです。Modelの属性名はクラス名(EchoForm)の先頭を小文字にしたものになります。この場合はechoForm
です4。
@RequestMapping
アノテーションは、URLリクエストのマッピングをしています。
自分のざっくりした理解では、@RequestMapping
単体だと、ディレクトリパスなしのURL直下にアクセスした時の挙動と思っています。valueを指定するとルートページからの相対パスが指定でき、methodは見た通り、受け付けるHTTPリクエストの種類を指定できます。現在の実装だと、以下の挙動になります。
- indexメソッドは
http://{サーバー名}
というURLへのリクエストで起動し、”index”というview名をreturnします。 - echoメソッドは
http://{サーバー名}/echo
というURLへのリクエストで起動し、”echo”というview名をreturnします。
POSTしか受け付けていないため、サーバー起動後直にhttp://{サーバー名}/echo
でGETリクエストをすると、以下のエラーが発生します。
②フォームクラスの作成
コントローラーで既に出てきましたが、テキストフィールドの値を受け取るためのフォームオブジェクトとして、EchoFormクラスの実装も必要です。getter/setterでnameプロパティをやり取りするだけのシンプルなクラスを実装しました。
package com.example.form;
import java.io.Serializable;
public class EchoForm implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
③Viewの作成…っていうかThymeleafってなんなんだ?
よ〜しロジックはできたぞ〜!あとはガワだ〜!JSPでしょ?知ってる知ってる!
…というように、View=JSPだとばかり思っていた人間です。
なので『Spring徹底入門』で以下記述を見たときに、控えめに言って絶望しました。
JSPの利用はさまざまな制約があるため推奨されていないため、本書でも扱いません。(p.602)
おやおや?JSPがないと「「Hello もょもと」ページに遷移」のように、入力値によって生成するHTML自体を変えるような実装はできないのではないか??と思いました。実際に検索すると、Spring BootではJSPの使用はやはり非推奨となっているようです。
If possible, JSPs should be avoided. There are several known limitations when using them with embedded servlet containers.
え…どないすればええんや…?汎用なHTMLを作って…都度DOM操作する気か…??(よく分かってない)
ご安心ください。ちゃんと『Spring徹底入門』12章に書いてありました。
Thymeleafは、Webアプリケーションと親和性の高いテンプレートエンジンです。テンプレートエンジンとは、雛形となるドキュメント(テンプレート)に対し、可変データを埋め込むことで動的にドキュメントを生成する仕組みです。この仕組みは、MVCフレームワークのModelとViewを分割する考え方と親和性が高く、しばしばMVCフレームワークのViewとして利用されます。(p.554)
なるほどなるほど。テンプレートエンジンってそういうものなのですね。よく分からぬままDependenciesに入れてました。だめな人ですね🙅♂️
仕組みとしては、先ほど想像していた形に近く、HTMLをDOMに変換してから処理を行うそうです。
以下がindex.html
の実装です。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<link th:href="@{/style.css}" rel="stylesheet" type="text/css">
<title>Echo Application</title>
</head>
<body>
<h1>お返事bot TOP</h1>
<form th:object="${echoForm}" th:action="@{/echo}" method="post">
<label for="name">名前を入れてください:</label>
<input th:field="*{name}">
<input type="submit">
</form>
</body>
</html>
頭にth:とついている属性が、Thymeleaf固有の書き方になっています。
フォームクラスとModelの紐付けはコントローラーに付与した@ModelAttribute
アノテーションが行っていますが、ThymeleafとModelの紐付けは、以下の部分で行っています。
th:object="${echoForm}"
先述の通り@ModelAttribute
アノテーションは、Modelの属性名をクラス名(EchoForm)の先頭を小文字にしたものにしているため、echoFormという名称で正しいです。Thymeleaf記法の変数式に入れた${echoForm}
をobjectとして設定することで、入力値の受け渡しができるようになります。
th:action
はHTMLのaction属性と似たような働きです。ただし、パスの書き方がThymeleaf独自のものとなっています。なお、th:action
やth:href
の前に通常のaction属性やhref属性を設定しておくと、アプリの一部として動かす場合だけでなく、普通のHTMLとしても動くようです。ThymeleafのテンプレートはHTML5準拠のため、デザイナーとエンジニア間で共有できるのも強みですね。
「もょもと」を返すecho.htmlは以下のような実装となっています。
ここの変数名は、コントローラーのechoメソッド内の第一引数から来ているため、nameになっています。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<link th:href="@{/style.css}" rel="stylesheet" type="text/css">
<title>Echo Application</title>
</head>
<body>
<p th:text="|Hello ${name}|"></p>
<p><a th:href="@{/}">お返事bot TOP</a></p>
</body>
</html>
これで、もょもと完成です!!いええええい!!ぺぺぺ!!
おわりに
Springのプロジェクトを再度作ったので、前回より結構分かるようになっていた気がします…!
コントローラーとメインメソッドを分けたこともあって、どのアノテーションがどこに必要なのか、とかも分かりやすくなったのが良かったなと思います!規模が大きくなってきたら、index.htmlとecho.htmlもコントローラー分けてあげなきゃな…と思うなどしました。
Thymeleafは初見だったので、結構いろいろ調べました!最終的に『Spring徹底入門』が最強だったので、Springに手を出したい人は買って損はないです…!辞書的に使えます!
今回もお読みいただき、ありがとうございました!
-
調べたらSpring Boot 2.3.0が2020年5月15日、2.3.1が2020年6月12日にリリースされているのですね…1ヶ月スパン…早い…。前回はなかった2.4.0のスナップショットも出ていて、移り変わりの速さにびっくりしました。 ↩
-
のちにクラス名プレフィクスをEchoに変えたりしているので、特に参考にしなくて大丈夫です。 ↩
-
HTMLベターッはさすがにやめたくなったので、CSSはこちらのサイトの「ゆっくりゆっくり色変化」を参考にさせていただきました。「サイトの引き立て役はコレ! おしゃれすぎる背景をコピペで実装 【 HTML/CSS 】」https://deshinon.com/2019/03/06/background-oshare-kopipe/ ↩
-
こちらのサイトを参考にさせていただいています。「2.3. はじめてのSpring MVCアプリケーション」https://macchinetta.github.io/server-guideline-thymeleaf/current/ja/Overview/FirstApplication.html ↩