テンプレートエンジンfreemarker2.*で自作のタグを作成

2010/05/02 18:15

軽量テンプレートエンジン、freemarker2.*でJavaのカスタムタグ等の様に、特殊な動きを実装した自前のタグを定義しテンプレートの中で使える様にする方法を以下に示します。

テンプレートからの呼び出し方法は<@定義名 />となります。

まず、現時点で方法は2つあります。

一つはTemplateDirectiveModel、もう一つはTemplateTransformModelを実装する方法です。

freemarkerのバージョンが2.1くらいまではTemplateDirectiveModelが使えない為、TemplateTransformModelでやることになりますが、現在TemplateTransformModelは非推奨なので、なるべくTemplateDirectiveModelを使用しましょう。以下に実装方法を両方とも記載いたします。

【TemplateDirectiveModelでの実装】

1.TemplateDirectiveModelを継承したクラスを作成

/** ここから */

import java.io.IOException;
import java.util.Map;

import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;

public class CustomDerectiveModel implements TemplateDirectiveModel{   
    @Override
    public void execute(Environment env, Map map, TemplateModel[] tms,
        TemplateDirectiveBody tdb) throws TemplateException, IOException {
    }
}

/** ここまで */

 

2. freemarker.template.Configurationクラスのインスタンス生成

Configuration config = new Configuration();
config.setSharedVariable("cdm", new CustomDerectiveModel());

※1 "cdm"は任意。テンプレート呼び出し時の名前
※2 CustomDerectiveModelは上記で作成したクラス

 

3. freemarkerのテンプレートは以下の通り記述

/** ここから */

<@cdm attrA="属性値1" attrB="属性値2">bodyです</@cdm>

/** ここまで */

上記からCustomDerectiveModelのexecuteメソッドが呼び出されます。

attrA~の属性値1~はMap、「bodyです」はTemplateDirectiveBodyに入っています。

あとはWriterに書き込んでいくいくだけです。そこでの実装で注意する点はスレッドセーフにすることです。

サンプルソースは、英語ですが本家ドキュメントが詳しいので参考にして下さい。http://freemarker.sourceforge.net/docs/pgui_datamodel_directive.html

 

【TemplateTransformModelでの実装】

1.TemplateTransformModelを継承したクラスを作成

/** ここから */

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateTransformModel;

public class CustomTransformModel implements TemplateTransformModel{

    @Override
    public Writer getWriter(final Writer out, Map map)
            throws TemplateModelException, IOException {
        final StringBuilder buf = new StringBuilder();
        return null;
    }
}

/** ここまで */

 

2. freemarker.template.Configurationクラスのインスタンス生成

Configuration config = new Configuration();
config.setSharedVariable("ctm", new CustomTransformModel());

※1 "ctm"は任意。テンプレート呼び出し時の名前
※2 CustomTransformModelは上記で作成したクラス

 

3. freemarkerのテンプレートは以下の通り記述

/** ここから */

<@ctm attrA="属性値1" attrB="属性値2" />

/** ここまで */

上記からCustomTransformModelのgetWriterメソッドが呼び出されます。

attrA~の属性値1~はMapに入っています。当方式ではタグのネストは許されない様です。※ java.io.IOException: This transform does not allow nested content.

あとはWriterに書き込んでいくいくだけです。こちらも注意点はスレッドセーフにすることです。

サンプルソースは、英語ですが本家ドキュメントが詳しいので参考にして下さい。http://freemarker.sourceforge.net/docs/api/freemarker/template/TemplateTransformModel.html

以上です。