Secret Staircase

Java テンプレートエンジンの比較

これまでにいくつかの Java 用のテンプレートエンジンを見てきました。今回はそれらを比較します。

対象

  • JSP (非 JSF)
  • Velocity
  • FreeMarker
  • Handlebars.java
  • Scalate (SSP)

評価軸

評価軸として優先度の高いものから順に以下を考えます。

  • デフォルト HTML エスケープ
  • レイアウト機能
  • HTML 以外での利用

デフォルト HTML エスケープ

デフォルトで HTML エスケープされない場合、<c:out>${escape(...)} など明示的に書くことになりますが、書き忘れてしまう危険性があるのと、なにより書き忘れていないことの確認が大変難しいのが問題です。

デフォルトで HTML エスケープされる場合は、逆にエスケープしない箇所を ${unescape(...)} などと明示的に書くので、間違ってエスケープを外していないかこの箇所だけの確認で済みます。

テンプレートエンジンによっては特定のインターフェースを実装していたり、アノテーションが付いているなどクラス定義によりエスケープを回避できるものがあって、その場合も調べるのは容易です。Java のコードなので単体テストが書きやすい利点があります。

JSP

ELResolver を使ってデフォルトでエスケープすることができます。書き方にもよりますがエスケープできるのは String のみで、その他のクラスの toString の結果はエスケープされません。このような箇所の特定は非常に困難です。 [検証記事]({% post_url 2013-04-30-jsp-escape %})

Velocity

ReferenceInsertionEventHandler を使ってデフォルトでエスケープし、テンプレートでの変数名やクラス定義によりエスケープを回避できます。後者だけに限定してテンプレート側からエスケープの制御をできないようにしてしまうのがテストの書きやすさやエスケープ漏れの防止の観点で効果的でしょう。 [検証記事]({% post_url 2013-05-01-velocity-escape %})

FreeMarker

TemplateLoader をカスタマイズして自動的に <#escape> タグで囲むようにしてデフォルトエスケープを実現できます。[検証記事]({% post_url 2013-05-02-freemarker-escape %})

Handlebars.java

デフォルトで HTML エスケープされます。0.12.0 には JSP 同様に String 以外がエスケープされない問題がありますが新しいバージョンでは直っているはず。{% raw %}{{{ ... }}}{% endraw %} や SafeString クラスを使ってエスケープを回避することができます。テンプレートでのエスケープ回避が簡単すぎるのと、記号を随時変更できるのでエスケープしていない箇所の特定が難しそうな点は気になります。[検証記事]({% post_url 2013-05-04-handlebars-java %})

Scalate (SSP)

デフォルトで HTML エスケープされます。 [検証記事]({% post_url 2013-05-03-use-scalate-in-java %})

レイアウト機能

たいていのテンプレートエンジンは自前で何らかのレイアウト機能を持っています。不足の場合は Tiles や SiteMesh などのフレームワークを組み合わせても良いですが自前で簡単にセットアップできるのは強みです。

JSP

レイアウト機能はありません。

Velocity

標準ではありませんが SpringMVC と使う場合は VelocityLayoutView が使えます。

FreeMarker

マクロを使ってレイアウトを実現できます。参考サイト

Handlebars.java

Template Inheritance が使えます。他のテンプレートエンジンに比べて高機能です。

Scalate

標準でレイアウト機能があります。

HTML 以外での利用

Web アプリケーションではメール送信などでテンプレートエンジンを使う機会があるので、HTML 以外でも使えるとテンプレートエンジンを 1 つで済ませられるので便利です。

比較

以上の内容を表にしてみました。 (オリジナルサイズ)

Velocity が良いですね。レイアウトはそのままでもまずまずの機能がありますし、Tiles を使ったり自前の VelocityView を作って改善することも可能です。

Handlebars.java も優秀です。クライアントサイドで Handlebars を使う場合はテンプレート記法を統一できる利点もありますね。API も今風で使いやすいです。エスケープ回避の記法が自由すぎてエスケープしていない箇所を見つけにくいのが弱点で、この点をきっちりしたいなら Velocity の方がいいでしょう。

結論としては、安定指向なら Veolocity、高度なレイアウト機能やクライアントと同じ記法を使いたいなら Handlebars.java が良さそうです。

今回の観点では JSP を採用する理由はありません。(JSF はだいぶ違うのでこの限りではありません)

FreeMarker は Velocity と似ているので好みでどちらかを選べば良いでしょう。

Scalate は Java から使うときに多少の考慮が必要なので、素直に他の Java テンプレートエンジンを使った方が良いです。[詳細]({% post_url 2013-05-03-use-scalate-in-java %})

  • 検証に使ったソースコードは github にあります
  • こちらのサイトで動作を確認できます (非常に遅いです)