「Thymeleaf + Spring Framework」のテンプレート機能として、インライン式で名称に数字を使用する場合は、指定する名称により想定していた動作と異なることがありました。
今回は、指定する名称の違いによる動作例とサンプルコードを紹介していきます。
ライブラリ
検証に使用した環境/ライブラリを以下に記載します。
- Java
- バージョン:11
- Spring Framework
- バージョン:5.2.8.RELEASE
- Thymeleaf
- バージョン:3.0.11.RELEASE
名称の指定方法
数字のみを指定する
名称に数字のみを指定したインライン式の場合は、次のような動作となります。
org.thymeleaf.TemplateEngine templateEngine = new org.thymeleaf.spring5.SpringTemplateEngine();
templateEngine.addTemplateResolver(new org.thymeleaf.templateresolver.StringTemplateResolver());
org.thymeleaf.context.Context context = new org.thymeleaf.context.Context(Locale.getDefault());
Map<String, Object> params = new HashMap<>();
params.put("0", "key-0");
context.setVariables(params);
String process = templateEngine.process("[[${0}]]", context);
System.out.println(process);
// 「0」が出力されます。
この指定方法は、出力結果が期待通りの値になりません。
出力結果は、パラメータに指定した「key-0」が出力されるのではなく、名称が置換されずに「0」が出力されます。
推測になりますが、指定した名称が変数名を表すのではなく、単なる数字と解釈された可能性があります。
javaでメッセージをフォーマット指定で出力できる、java.text.MessageFormatクラスと同じ方法で使用してしまうとこの問題が発生することがあります。
英字のみを指定する
名称に英字のみを指定したインライン式の場合は、次のような動作となります。
org.thymeleaf.TemplateEngine templateEngine = new org.thymeleaf.spring5.SpringTemplateEngine();
templateEngine.addTemplateResolver(new org.thymeleaf.templateresolver.StringTemplateResolver());
org.thymeleaf.context.Context context = new org.thymeleaf.context.Context(Locale.getDefault());
Map<String, Object> params = new HashMap<>();
params.put("a", "key-a");
context.setVariables(params);
String process = templateEngine.process("[[${a}]]", context);
System.out.println(process);
// 「key-a」が出力される。
この指定方法は、出力結果が期待通りの値になります。
出力結果は、指定した名称が変数に置換されて「key-a」が出力されます。
英数字のみ(先頭が数字以外)を指定する
名称に英数字のみ(先頭は数字以外)を指定したインライン式の場合は、次のような動作となります。
org.thymeleaf.TemplateEngine templateEngine = new org.thymeleaf.spring5.SpringTemplateEngine();
templateEngine.addTemplateResolver(new org.thymeleaf.templateresolver.StringTemplateResolver());
org.thymeleaf.context.Context context = new org.thymeleaf.context.Context(Locale.getDefault());
Map<String, Object> params = new HashMap<>();
params.put("a0a", "key-a0a");
context.setVariables(params);
String process = templateEngine.process("[[${a0a}]]", context);
System.out.println(process);
// 「key-a0a」が出力されます。
この指定方法は、出力結果が期待通りの値になります。
出力結果は、指定した名称が変数に置換されて「key-a0a」が出力されます。
英数字のみ(先頭が数字)を指定する
名称に英数字のみ(先頭は数字)を指定した場合は、次のような動作となります。
org.thymeleaf.TemplateEngine templateEngine = new org.thymeleaf.spring5.SpringTemplateEngine();
templateEngine.addTemplateResolver(new org.thymeleaf.templateresolver.StringTemplateResolver());
org.thymeleaf.context.Context context = new org.thymeleaf.context.Context(Locale.getDefault());
Map<String, Object> params = new HashMap<>();
params.put("0a", "key-0a");
context.setVariables(params);
String process = templateEngine.process("[[${0a}]]", context);
System.out.println(process);
// 「org.thymeleaf.exceptions.TemplateInputException」の例外が発生する。
この指定方法では、実行時に次の例外が発生します。
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "[[${0a}]]")
まとめ
Thymeleafでインライン式の名称に数字を指定する場合は、指定する場所により動作が異なることがあるため注意してください。