概要
- Spring Boot で Mustache テンプレートエンジンを使う
- 今回の動作確認環境: Java 14 (AdoptOpenJDK 14.0.2+12) + Spring Boot 2.3.2 + Gradle 6.5.1 + macOS Catalina
サンプルコード
ソースコード一覧
├── build.gradle
└── src
└── main
├── java
│ └── com
│ └── example
│ ├── SampleController.java
│ └── SampleData.java
└── resources
├── application.properties
└── templates
├── error
│ ├── 4xx.html
│ └── 5xx.html
└── my_template.html
build.gradle
Spring Boot Starter Mustache を導入する。
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1'
sourceCompatibility = '14'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-web'
}
spring-boot-starter-mustache-2.3.2.RELEASE.pom の中身を見ると Spring Boot Starter Mustache が Mustache ライブラリの JMustache 1.15 を利用していることがわかる。
src/main/resources/application.properties
Mustache に関する設定を行う。
ここでは拡張子が html のファイルをテンプレートファイルとして扱うように spring.mustache.suffix を設定する。
# テンプレートのキャッシュを有効にするかどうか (デフォルト値: false)
spring.mustache.cache=false
# テンプレートのエンコード (デフォルト値: UTF-8)
spring.mustache.charset=UTF-8
# テンプレート名に適用するプレフィックス (デフォルト値: classpath:/templates/)
spring.mustache.prefix=classpath:/templates/
# テンプレート名に適用するサフィックス (デフォルト値: .mustache)
spring.mustache.suffix=.html
他にも設定項目があるので必要に応じて Spring Boot アプリケーションプロパティ一覧 - ドキュメント などを参照すると良い。
src/main/java/com/example/SampleController.java
コントローラークラス。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@SpringBootApplication
@Controller
public class SampleController {
public static void main(String[] args) {
SpringApplication.run(SampleController.class, args);
}
@GetMapping("/mypage")
public ModelAndView mypage() {
SampleData sampleData = new SampleData();
ModelAndView mav = new ModelAndView();
mav.setViewName("my_template"); // テンプレートファイル名
mav.addObject("mydata", sampleData); // データオブジェクトをセット
return mav;
}
@GetMapping("/myerror")
public ModelAndView myerror() {
throw new RuntimeException("エラーを発生させる");
}
}
src/main/java/com/example/SampleData.java
Mustache テンプレートに埋め込むデータオブジェクト。
package com.example;
import java.util.List;
import java.util.Map;
public class SampleData {
public String foo = "foo";
public String getBar() {
return "bar";
}
public String[] strings = {"S1", "S2", "S3"};
public List list = List.of("L1", "L2", "L3");
public Map map = Map.of("key1", "value1", "key2", "value2", "key3", "value3");
}
src/main/resources/templates/my_template.html
データオブジェクトの内容を表示するための Mustache テンプレートファイル。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{#mydata}}
foo: {{foo}}<br>
getBar(): {{bar}}<br>
{{/mydata}}
<br>
strings:<br>
{{#mydata.strings}}
value: {{.}}<br>
{{/mydata.strings}}
<br>
list:<br>
{{#mydata.list}}
value: {{.}}<br>
{{/mydata.list}}
<br>
map:<br>
{{#mydata.map}}
{{key1}}, {{key2}}, {{key3}}
{{/mydata.map}}
</body>
</html>
src/main/resources/templates/error/4xx.html
4xx 系エラー発生時のための Mustache テンプレートファイル。
必要に応じてエラー情報等のデータを埋め込むことができる。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>4xx</title>
</head>
<body>
<h1>4xx</h1>
<div>timestamp: {{#timestamp}}{{.}}{{/timestamp}}</div>
<div>status: {{#status}}{{.}}{{/status}}</div>
<div>error: {{#error}}{{.}}{{/error}}</div>
<div>exception: {{#exception}}{{.}}{{/exception}}</div>
<div>message: {{#message}}{{.}}{{/message}}</div>
<div>errors: {{#errors}}{{.}}{{/errors}}</div>
<div>trace: {{#trace}}{{.}}{{/trace}}</div>
<div>path: {{#path}}{{.}}{{/path}}</div>
</body>
</html>
src/main/resources/templates/error/5xx.html
5xx 系エラー発生時のための Mustache テンプレートファイル。
必要に応じてエラー情報等のデータを埋め込むことができる。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>5xx</title>
</head>
<body>
<h1>5xx</h1>
<div>timestamp: {{#timestamp}}{{.}}{{/timestamp}}</div>
<div>status: {{#status}}{{.}}{{/status}}</div>
<div>error: {{#error}}{{.}}{{/error}}</div>
<div>exception: {{#exception}}{{.}}{{/exception}}</div>
<div>message: {{#message}}{{.}}{{/message}}</div>
<div>errors: {{#errors}}{{.}}{{/errors}}</div>
<div>trace: {{#trace}}{{.}}{{/trace}}</div>
<div>path: {{#path}}{{.}}{{/path}}</div>
</body>
</html>
出力結果例
curl でアクセスしてレスポンス結果を確認する。
正常レスポンスのとき
データオブジェクトが Mustache テンプレートに埋め込まれて出力されている。
$ curl http://localhost:8080/mypage
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
foo: foo<br>
getBar(): bar<br>
<br>
strings:<br>
value: S1<br>
value: S2<br>
value: S3<br>
<br>
list:<br>
value: L1<br>
value: L2<br>
value: L3<br>
<br>
map:<br>
value1, value2, value3
</body>
</html>
404 Not Found のとき
4xx 系エラー発生時のための Mustache テンプレートファイルにエラー情報が埋め込まれて出力されている。
$ curl --include -H "accept: text/html" http://localhost:8080/
HTTP/1.1 404
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: text/html;charset=UTF-8
Content-Language: ja-JP
Content-Length: 321
Date: Fri, 07 Aug 2020 07:55:53 GMT
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>4xx</title>
</head>
<body>
<h1>4xx</h1>
<div>timestamp: Fri Aug 07 16:55:53 JST 2020</div>
<div>status: 404</div>
<div>error: Not Found</div>
<div>exception: </div>
<div>message: </div>
<div>errors: </div>
<div>trace: </div>
<div>path: /</div>
</body>
</html>
エラー発生時
5xx 系エラー発生時のための Mustache テンプレートファイルにエラー情報が埋め込まれて出力されている。
$ curl --include -H "accept: text/html" http://localhost:8080/myerror
HTTP/1.1 500
Content-Type: text/html;charset=UTF-8
Content-Language: ja-JP
Content-Length: 340
Date: Fri, 07 Aug 2020 07:55:47 GMT
Connection: close
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>5xx</title>
</head>
<body>
<h1>5xx</h1>
<div>timestamp: Fri Aug 07 16:55:47 JST 2020</div>
<div>status: 500</div>
<div>error: Internal Server Error</div>
<div>exception: </div>
<div>message: </div>
<div>errors: </div>
<div>trace: </div>
<div>path: /myerror</div>
</body>
</html>
参考資料
Spring Boot 「使い方」ガイド - 公式ドキュメントの日本語訳
Mustache を使用する場合、「mustacheViewResolver」という名前の MustacheViewResolver もあります。ビュー名をプレフィックスとサフィックスで囲むことにより、リソースを探します。プレフィックスは spring.mustache.prefix で、サフィックスは spring.mustache.suffix です。接頭辞と接尾辞の値は、デフォルトでそれぞれ「classpath:/templates/」と「.mustache」になります。同じ名前の Bean を提供することにより、MustacheViewResolver をオーバーライドできます。
- Spring Boot の機能 - 公式ドキュメントの日本語訳
- Spring Boot アプリケーションプロパティ一覧 - ドキュメント
- spring-boot/MustacheView.java at v2.3.2.RELEASE · spring-projects/spring-boot · GitHub
- spring-boot/MustacheViewResolver.java at v2.3.2.RELEASE · spring-projects/spring-boot · GitHub
- spring-boot/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mustache at v2.3.2.RELEASE · spring-projects/spring-boot · GitHub
- 7.2.6. エラー処理 - Spring Boot の機能 - 公式ドキュメントの日本語訳
- DefaultErrorAttributes (Spring Boot 2.3.2.RELEASE API)
- Guide to Mustache with Spring Boot | Baeldung