素の Java プロジェクトで SpEL 式の Thymeleaf を使うまで
素の Java プロジェクトで Thymeleaf を使うのであれば、 org.thymeleaf:thymeleaf
をライブラリに追加すれば良い。
Gradle の場合
dependencies {
+ // https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf
+ implementation group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.12.RELEASE'
}
ただし、これだと Thymeleaf の式言語が標準の OGNL になってしまうので、どうにか Spring のプロジェクトではないけど、式言語を SpEL (Spring Expression Language) にしたくて、検証してみました。
余談として、Spring Boot で何気なく使用していた Thymeleaf の各種演算子が実は Spring の独自拡張で、Spring を用いたプロジェクトではなく、素の Thymeleaf を使っている案件に入った際に気付かされて Spring 様様だなと痛感した次第。
結論 依存ライブラリ
org.thymeleaf:thymeleaf-spring5
と org.springframework:spring-context
を追加して Thymeleaf の実装をすれば SpEL 式でテンプレートを記述することができました。
Gradle の場合
dependencies {
+ // https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf-spring5
+ implementation group: 'org.thymeleaf', name: 'thymeleaf-spring5', version: '3.0.12.RELEASE'
+ // https://mvnrepository.com/artifact/org.springframework/spring-context
+ implementation group: 'org.springframework', name: 'spring-context', version: '5.3.9'
}
実装例
実際に Gradle で素の Java プロジェクトを作成した後、SpEL 式な Thymeleaf を使う実装を備忘録程度に残しておきます。
Main クラス
src/main/java/Main.java
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
public class Main {
public static void main(String[] args) {
// configure template file resolver
var resolver = new ClassLoaderTemplateResolver();
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setPrefix("template/");
resolver.setSuffix(".html");
// init template engine
var templateEngine = new SpringTemplateEngine();
templateEngine.setEnableSpringELCompiler(true);
templateEngine.setTemplateResolver(resolver);
var result = templateEngine.process("index", new Context());
System.out.println(result);
}
}
src/resouces/index.html
のテンプレートファイルの処理結果を sysout するシンプルな処理になっています。
org.thymeleaf.spring5.SpringTemplateEngine
を使用しているのが点が素の Thymeleaf のライブラリを使用する場合との差分になります。
setEnableSpringELCompiler(true);
は以下のドキュメントを見ると、高速化するよとだけ書いていたのでとりあえず記載していますが、流石に今回のレベルの処理だと体感速度は変わらなかったです。
テンプレートファイル
src/main/resouces/index.html
<!doctype html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<title>Document</title>
<h1 th:text="'Hello World.'"
th:data-hoge="${ 'example' }"></h1>
<ul>
<li th:each="item : ${ nullable ?: {} }"></li>
</ul>
</html>
Main
クラスでは nullable
というコンテキストを定義していないので null
となり、Thymeleaf の処理を走らせようとすると NullPointerException
が本来は発生してしまうのですが、OGNL 式にはなく SpEL 式には存在するエルビスオペレーター (Elvis Operator) を使用して例外エラーにならないように記述しています。
もし、式言語が OGNL でこの例外エラーを回避する場合は以下のような処理になり、やや冗長さを感じてしまいます。
<ul>
<li th:each="item : ${ nullable } ? ${ nullable } : ${ {} }"></li>
</ul>
他にも、オプショナルチェイニング演算子 (Safe Navigation operator) なども使えるので、一度 SpEL 式で調べてみると良いかもしれないです。
Main クラス実行結果
例外エラーも発生せずに <li>
要素が出力されていないことが確認できます。
<!doctype html>
<html lang="ja">
<title>Document</title>
<h1 data-hoge="example">Hello World.</h1>
<ul>
</ul>
</html>
以上、できるだけ最低限のライブラリだけで SpEL 式で Thymeleaf を実行してみました。
~~本当は Spring MVC とか Spring Boot 上でやればいいんだけどね……~~