URLのテンプレート化
前回に引き続き、Javaアプリケーション用テンプレートエンジン「Thymeleaf」の使い方を紹介する。標準の文法セットである「Standard Dialects」に用意された文法として#{●●●}と${●●●}、そして*{●●●}という3種類を取り上げたが、Standard Dialectsにはもうひとつ「@{●●●}」という記述方法が存在する。これはURL形式の文字列を生成するための構文である。
例えば次のように記述したとする。
@{/hoge/piyo}
テンプレートエンジンで処理を行った結果、この部分はコンテキストルート以下の「/hoge/piyo」というパスに置き換えられる。この記述法の大きなメリットは、次のように${●●●}と組み合わせることで、パラメータとしてサーバ側のオブジェクトの値を渡すことができるという点である。
@{/hoge/piyo(parameter=${param1}}
この例の場合、もし変数param1の値が「foo」であったとすれば、生成されるURLは「/hoge/piyo?parameter=foo」となり、param1が「bar」であれば、URLは「/hoge/piyo?parameter=bar」となる。このように動的にURLを生成することができる。
この構文は、aタグのth:href属性や、fromタグのth:action属性とセットで使用される。th:hrefはaタグのリンク先を指定するためのもの属性であり、次のように記述する。
<div style="font-size:20px"><strong>
<a href="link.html"
th:href="@{http://localhost:8080/ThymeleafSample/link.html(par=${param})}">リンク</a>
</strong></div>
${param}の部分はサーバ側のコンテキストに設定されたparamの値に置き換わる。例えばサーバ側プログラムでparamの値を次のように設定したとする。
// WebContextを作成
WebContext ctx = new WebContext(request, request.getLocale());
// オブジェクトをセット
ctx.setVariable("param", "value");
// テンプレートの処理を実行
String result = engine.process("link", ctx);
すると、テンプレートエンジンの処理によって生成されるHTMLコードは以下のようになる。
<div style="font-size:20px"><strong>
<a href="http://localhost:8080/ThymeleafSample/link.html?par=value" shape="rect">リンク</a>
</strong></div>
formタグのアクションを指定する場合でも、th:action属性で同様の記法を利用することができる。
Thymeleafをスタンドアロンプログラムで利用する
これまでの例では、Webアプリケーション(Servlet)におけるHTMLの生成に対してThymeleafのテンプレートエンジンを利用してきた。しかしThymeleafには、Webアプリケーションだけでなく、スタンドアロンのアプリケーションから利用するための仕組みも備えられている。そこで、今度はServletを利用しない、スタンドアロンのJavaプログラムにおいて、XMLコードの生成にThymeleafを利用してみよう。
鍵となるのはTemplateResolverである。Webアプリケーションの場合には、ServletContextTemplateResolverというクラスを利用することで、Servletコンテキスト内でのテンプレート処理を適切に行うことができた。Thymeleafに標準で用意されたTemplateResolverとしては、その他にファイルからテンプレートを読み込むFileTemplateResolver、URLからテンプレートを読み込むUrlTemplateResolver、そしてクラスローダを利用してテンプレートを読み込むClassLoaderTemplateResolverが用意されている。ここでは、もっとも一般的であるFileTemplateResolverを使ってみる。
FileTemplateResolverもServletContextTemplateResolverと同様にTemplateResolverクラスのサブクラスなので、基本的な使い方は変わらない。以下はプレフィックスとして「C:\templates\」フォルダを、サフィックスとして拡張子「.xml」をセットしてFileTemplateResolverオブジェクトを生成した例である。今回はXMLの生成に利用するので、テンプレートモードとしてはTemplateMode.XMLを設定している。
// TemplateResolverを作成
FileTemplateResolver resolver = new FileTemplateResolver();
resolver.setTemplateMode(TemplateMode.XML); // テンプレートモード
resolver.setPrefix("C:\\templates\\"); // プレフィックス
resolver.setSuffix(".xml"); // サフィックス
テンプレート処理に利用するコンテキストとしてはWebアプリケーションの場合はWebContextクラスを利用したが、スタンドアロンの場合には標準的な実装としてContextクラスが用意されているので、これを利用することにする。以下は、Contextを生成してAccountオブジェクトのリストをセットする例である。これも基本的な手順はWebContextの場合と同様である。
// Contextオブジェクトを作成
Context ctx = new Context();
// オブジェクトをセット
List<Account> accounts = new ArrayList<Account>();
accounts.add(new Account("user1", "hogehoge"));
accounts.add(new Account("user2", "piyopiyo"));
accounts.add(new Account("user3", "hogepiyo"));
ctx.setVariable("accounts", accounts);
TemplateEngineには、上で生成したFileTemplateResolverオブジェクトをセットする。テンプレート処理の実行はこれまでと同様にprocess()メソッドで行えばよい。以下に、テンプレートとして「sample.xml」を、プロパティファイルとして「sample.properties」を用意し、それをもとに「result.xml」を生成するプログラムの例を示す。
package jp.mycom.toolde.Thmeleaf;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.thymeleaf.*;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.FileTemplateResolver;
public class ThymeleafSample {
public static void main(String[] args) {
// TemplateResolverを作成
FileTemplateResolver resolver = new FileTemplateResolver();
resolver.setTemplateMode(TemplateMode.XML); // テンプレートモード
resolver.setPrefix("C:\\templates\\"); // プレフィックス
resolver.setSuffix(".xml"); // サフィックス
// Contextオブジェクトを作成
Context ctx = new Context();
// オブジェクトをセット
List<Account> accounts = new ArrayList<Account>();
accounts.add(new Account("user1", "hogehoge"));
accounts.add(new Account("user2", "piyopiyo"));
accounts.add(new Account("user3", "hogepiyo"));
ctx.setVariable("accounts", accounts);
// TemplateEngineを作成
TemplateEngine engine = new TemplateEngine();
engine.setTemplateResolver(resolver);
// テンプレートの処理を実行
String result = engine.process("sample", ctx);
// 結果を出力
PrintWriter writer = null;
try {
writer = new PrintWriter(new FileWriter("result.xml"));
writer.println(result);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (writer != null) {
writer.close();
}
}
}
}
sample.xmlの記述は次のようにした。
<?xml version="1.0" encoding="UTF-8"?>
<acountlist xmlns:th="http://www.thymeleaf.org">
<title th:text="#{title}">タイトル</title>
<account th:each="account: ${accounts}">
<id th:text="${account.id}">ユーザID</id>
<password th:text="${account.password}">パスワード</password>
</account>
</acountlist>
また、sample.propertiesには次のように記述した。
title=XMLにおけるTymeleafの利用例
ここで使っているのはStandard Dialectsに用意された文法だけなので、テンプレートの内容についてはServletの例とほぼ同様である。このプログラムを実行して生成されたresult.xmlは次のようになった。
このように、Webアプリケーションだけでなく、さまざまな場面でのテキスト処理に活用できるのがThymeleafの強みである。さらにTemplateResolverやDialectsのカスタマイズも可能なため、ニーズに合わせた柔軟な対応が可能である。公式サイトのドキュメントにはDiarectsの拡張方法などもまとめられているので、より深く知りたい方は参照してみるといいだろう。