FreeMarkerってべんりですよね!
functionとかmacroで簡単なロジックも書けたりとか!
でもなんかもうちょっとfunctionで色々やりたいとか思ったりもしますよね!しませんか!
ぼくはしたのでやってみました!
FreeMarker Manual - FAQ
FreeMarker Manual - Bean wrapper
このへんを軽く流し読みした限りだとTemplateMethodModelExを実装したクラスをConfiguration#setSharedVariableにぶちこめばいける雰囲気です。
その前にTemplateMethodModelっていうのもあってこれがTemplateMethodModelExと何が違うのかわかんないのでjavadocを見ます。
TemplateMethodModel (FreeMarker 2.3.20 API)
TemplateMethodModelEx (FreeMarker 2.3.20 API)
英語よくわかんないですけどなんか多分実装しないといけないexecメソッドの引数の型が違う感じっぽい。
TemplateMethodModelだと問答無用でStringが入ってくるけどTemplateMethodModelExだとちゃんと望んだ型で取れる的な。きっと。そんなかんじ。
今回はためしに引数として渡ってきたStringをStringEscapeUtils#escapeHtmlでエスケープして返すfunctionを作ってみます。
まずはTemplateMethodModelExの実装クラスを作ります。
public class HtmlEscapeUtil implements TemplateMethodModelEx { @Override public Object exec(List args) throws TemplateModelException { if(CollectionUtils.isEmpty(args)){ throw new TemplateModelException("wrong size."); } Object arg0 = args.get(0); String str = null; if (arg0 instanceof TemplateScalarModel){ str = ((TemplateScalarModel)arg0).getAsString(); } return StringEscapeUtils.escapeHtml(str); } }
javadocに記述がある通りTemplateMethodModelExにおけるexecの引数はTemplateModelのListです。
今回は引数がStringのはずなのでTemplateScalarModelのインスタンスであるかどうか確認して、正しければStringとして取得する形にしてます。
TemplateModelについては以下のjavadocを。
TemplateModel (FreeMarker 2.3.20 API)
次はこいつを実際に使えるようにしてやります。
今回のような拡張をしない場合、Springだとorg.springframework.web.servlet.view.freemarker.FreeMarkerConfigurerをbean定義してると思うんですが、今回はこいつを継承したクラスを作ります。
public class CustomFreeMarkerConfigurer extends FreeMarkerConfigurer { @Override public Configuration createConfiguration() throws IOException, TemplateException { Configuration config = super.createConfiguration(); // TemplateMethodModelExを実装したクラスを「htmlEscape」としてセット config.setSharedVariable("htmlEscape", new HtmlEscapeUtil()); return config; } }
的な!感じで!
あとはこのクラスをFreeMarkerConfigurerの代わりにbean定義してやればあとはftlから呼び出すだけです!
${htmlEscape("<hoge>")}
いけた!すてきね!