Thymeleaf 3.0を試す その3 ユーティリティを作る
・Thymeleaf 3.0を試す
・Thymeleaf 3.0を試す その2 エスケープの有無
の続き。
今までパラメータとして文字列しか渡していませんでしたが、もちろん数値も扱えます。
〜 String template = "[[${a}]] + [[${b}]] = [[${a+b}]]"; 〜 Map<String, Object> params = new HashMap<>(); params.put("a", 1000); params.put("b", 20000); 〜
計算もView側でできるのがわかりますね。
実行結果
1000 + 20000 = 21000
3桁区切り
3ケタごとに区切り文字を入れたいというのはよくあることです。もちろんそれも標準で用意はされてはいます。一応。
〜
String template = "[[${#numbers.formatInteger(a+b, 1, 'DEFAULT')}]]";
〜
実行結果
21,000
一応と書いたのは、見てわかる通りあほみたいに長いのが原因です。
実行しないとこのミスはわからないしこんなのいちいち書いてられないと思います。書いていたらおかしいと思わないといけませんよね。
オレオレutil
というわけで作ります。まずシンプルに何も考えず現在できる仕組みの中で考えてみましょう。
//---------------------------------------------------------------------- //追加したいユーティリティ //---------------------------------------------------------------------- class OreOreUtil { public String num(int num){ NumberFormat nf = NumberFormat.getInstance(); return nf.format(num); } } 〜 String template = "[[${oreore.num(a+b)}]]"; 〜 Map<String, Object> params = new HashMap<>(); params.put("a", 1000); params.put("b", 20000); params.put("oreore", new OreOreUtil()); 〜
実行結果
21,000
まずはこれで十分だと思います。しいて言えばユーティリティなのかパラメータなのかどうかがわかりにくいです。パラメータとして渡していますので。「#」は予約されていてパラメータの名前として使えないのでこうなります。
が、命名規則でどうにでもなるとは思いますので気になる人だけ次に進むとよいでしょう。
複雑化させる仕組みは必須ではないと思います。
まじめに実装する
dialectという拡張する仕組みがどうやらあるぽいです。全ソースコードを載せます。
import java.text.NumberFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import org.thymeleaf.context.IContext; import org.thymeleaf.context.IExpressionContext; import org.thymeleaf.dialect.IExpressionObjectDialect; import org.thymeleaf.expression.IExpressionObjectFactory; public class Thymeleaf3 { public static void main(String[] args) { //---------------------------------------------------------------------- //追加したいユーティリティ //---------------------------------------------------------------------- class OreOreUtil { public String num(int param){ NumberFormat nf = NumberFormat.getInstance(); return nf.format(param); } } //---------------------------------------------------------------------- //「#oreore」という名前でOreOreUtilにアクセスさせるためのしくみ //---------------------------------------------------------------------- class OreOreDialect implements IExpressionObjectDialect{ final static String KEY = "oreore"; final Set<String> names = new HashSet<String>(){ {add(KEY);} }; @Override public IExpressionObjectFactory getExpressionObjectFactory() { return new IExpressionObjectFactory() { @Override public Set<String> getAllExpressionObjectNames() { return names; } @Override public Object buildObject(IExpressionContext context, String expressionObjectName) { if(KEY.equals(expressionObjectName)){//名前が一致したなら return new OreOreUtil(); } return null; } @Override public boolean isCacheable(String expressionObjectName) { return true; } }; } @Override public String getName() { return "OreOreUtilDialect"; } } //---------------------------------------------------------------------- //ここから下が実行 //---------------------------------------------------------------------- //準備 TemplateEngine engine = new TemplateEngine(); //オレオレ設定追加 engine.addDialect(new OreOreDialect()); String template = "[[${#oreore.num(a+b)}]]"; Map<String, Object> params = new HashMap<>(); params.put("a", 1000); params.put("b", 20000); IContext context = new Context(Locale.getDefault(), params); //生成 String result = engine.process(template, context); //出力 System.out.println(result); } }
実行結果は同じです。
21,000
#oreore.num()でアクセスできているのがわかりますね。