1. ホーム
  2. java

[解決済み] Freemarkerにオブジェクトのリストを渡し、ループさせる

2022-02-18 18:13:47

質問

Java用のテンプレートエンジンであるFreeMarkerを使いこなしています。

Hash Mapを介してテンプレートエンジンにオブジェクトを渡すことができるようになった。これは問題なく動作します。しかし、複数のオブジェクトのセットを FreeMarker に渡そうとすると、すぐに freemarker.template.TemplateException が発生して、 "Expected collection or sequence.jobs evaluated instead to freemarker.template.SimpleHash" と文句を言ってきます。

いろいろな資料を読んで理解したところでは、これは予想されることです。

今、私は多くの足跡を残し、これを回避する方法について多くの人々がコメントしているのを発見しました。しかし、率直に言って、(a) 多くの例で、彼らのアドバイスが私のケースにどのように当てはまるのかが不明確でした。

私がやりたいことは、最も単純化されたレベルでは、基本的に次のようなことです。

  1. 簡単なServletを持っています。

  2. いくつかのメソッドとプロパティを持つ単純なクラス(この例ではInvoiceという名前)を持っています。

  3. サーブレットに、これらのオブジェクトのインスタンス (またはこれらのオブジェクトのビュー) のリスト/配列/シーケンス/ハッシュマップを (何らかの方法で) FreeMarker の process メソッドに表示させたいと思います。

  4. .ftlテンプレートにリスト/配列/シーケンス/ハッシュマップのループを実行させ、以下のようなメソッドの結果を表示させたいのです。

< # list invoices as invoice> 
Invoice note: ${invoice.getNote()}, Invoice Amount:${invoice.getAmount()} 
< / # list>

さて、私は必ずしもこの件に関するクイック&アンプ;ダーティな解決策を探しているわけではありません。私はFreeMarkerの初心者ですが、エレガントで良いデザインの適切な方法でこれを行いたいと考えています。そのため、この方法を完全に見直すことに前向きです。どなたか、このようなことを実現するために必要なことを教えていただけませんか?

どのように解決するのか?

jobs"は本当にコレクションなのでしょうか?テンプレートを作成し、処理しているコードのスニペットを投稿してください。

確認のために簡単なテストを書いただけです。

public void testFreeMarker() throws Exception {

    List<Invoice> invoices = Arrays.asList(
       new Invoice( "note1", "amount1" ), 
       new Invoice( "note2", "amount2" ) );
    Map<String, Object> root = new HashMap<String, Object>();
    root.put( "invoices", invoices );
    StringWriter out = new StringWriter();

    Configuration cfg = new Configuration();
    cfg.setClassForTemplateLoading( FreemarkerUtils.class, "/templates" );
    cfg.setObjectWrapper( new DefaultObjectWrapper() );
    Template temp = cfg.getTemplate( "listTest.ftl" );
    temp.process( root, out );

    System.out.println( out.getBuffer().toString() );
}

テンプレートがあるだけです。

<#list invoices as invoice>
 Item: ${invoice.note} - ${invoice.amount}
</#list>

結果は予想通りです。

Item: note1 - amount1
Item: note2 - amount2