6

高度な Freemarker グルに注意:

単一の freemarker テンプレートを使用して、データとは別に定義された表示する列を使用して、任意の pojo のテーブルを出力できるようにしたいと考えています。問題は、実行時に pojo の関数へのハンドルを取得し、freemarker にその関数 (ラムダ スタイル) を呼び出す方法がわからないことです。ドキュメントをざっと読むと、Freemarker は関数型プログラミングをサポートしているように見えますが、適切な呪文を公式化することはできないようです。

単純化した具体例をまとめました。2 つのリストがあるとします。firstName と lastName を持つ人のリストと、make と model を持つ車のリストです。次の 2 つのテーブルを出力します。

<table>
  <tr>
    <th>firstName</th>
    <th>lastName</th>
  </tr>
  <tr>
    <td>Joe</td>
    <td>Blow</d>
  </tr>
  <tr>
    <td>Mary</td>
    <td>Jane</d>
  </tr>
</table>

<table>
  <tr>
    <th>make</th>
    <th>model</th>
  </tr>
  <tr>
    <td>Toyota</td>
    <td>Tundra</d>
  </tr>
  <tr>
    <td>Honda</td>
    <td>Odyssey</d>
  </tr>
</table>

しかし、これは何十もの異なる pojo タイプを処理する必要があるフレームワークの一部であるため、同じテンプレートを使用したいと考えています。

次のコードがあるとします。

public class FreemarkerTest {

  public static class Table {
    private final List<Column> columns = new ArrayList<Column>();

    public Table(Column[] columns) {
      this.columns.addAll(Arrays.asList(columns));
    }

    public List<Column> getColumns() {
      return columns;
    }

  }

  public static class Column {
    private final String name;

    public Column(String name) {
      this.name = name;
    }

    public String getName() {
      return name;
    }
  }

  public static class Person {
    private final String firstName;
    private final String lastName;

    public Person(String firstName, String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
    }

    public String getFirstName() {
      return firstName;
    }

    public String getLastName() {
      return lastName;
    }
  }

  public static class Car {
    String make;
    String model;

    public Car(String make, String model) {
      this.make = make;
      this.model = model;
    }

    public String getMake() {
      return make;
    }

    public String getModel() {
      return model;
    }
  }

  public static void main(String[] args) throws Exception {
    final Table personTableDefinition = new Table(new Column[] { new Column("firstName"), new Column("lastName") });
    final List<Person> people = Arrays.asList(new Person[] { new Person("Joe", "Blow"), new Person("Mary", "Jane") });
    final Table carTable = new Table(new Column[] { new Column("make"), new Column("model") });
    final List<Car> cars = Arrays.asList(new Car[] { new Car("Toyota", "Tundra"), new Car("Honda", "Odyssey") });

    final Configuration cfg = new Configuration();
    cfg.setClassForTemplateLoading(FreemarkerTest.class, "");
    cfg.setObjectWrapper(new DefaultObjectWrapper());
    final Template template = cfg.getTemplate("test.ftl");

    process(template, personTableDefinition, people);
    process(template, carTable, cars);
  }

  private static void process(Template template, Table tableDefinition, List<? extends Object> data) throws Exception {
    final Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("tableDefinition", tableDefinition);
    dataMap.put("data", data);
    final Writer out = new OutputStreamWriter(System.out);
    template.process(dataMap, out);
    out.flush();
  }

}

上記のすべてがこの問題に当てはまります。これが私がハッキングしてきたテンプレートです。私が問題を抱えているコメントに注意してください。

<table>
  <tr>
<#list tableDefinition.columns as col>
    <th>${col.name}</th>
</#list>
  </tr>
<#list data as pojo>
  <tr>
<#list tableDefinition.columns as col>
    <td><#-- what goes here? --></td>    
</#list>  
  </tr>
</#list>
</table>

したがって、col.name には、pojo からアクセスしたいプロパティの名前が含まれています。私はいくつかのことを試しました。

pojo.col.name

<#assign property = col.name/>
${pojo.property}

もちろん、これらは機能しません。意図を伝えるためにそれらを含めただけです。関数へのハンドルを取得して freemarker に呼び出させる方法、または任意の式を文字列として取り、実行時に評価できる何らかの「評価」機能を探しています。

4

2 に答える 2

5

?evalこれは (ほとんど?) 常に悪い考えです。なぜなら、多くの場合、パフォーマンスの欠点 (多くの解析など) やセキュリティの問題 (「FTL インジェクション」など) が伴うためです。

より良いアプローチは、角かっこの構文を使用することです。

サブ変数名を式で指定したい場合は、別の構文があります: book["title"]. 角括弧では、文字列に評価される限り、任意の式を指定できます。

(ハッシュからのデータの取得に関する FreeMarker のドキュメントから)

あなたの場合、次のようなものをお勧めします${pojo[col.name]}

于 2011-05-17T14:33:05.483 に答える
2

答えを見つけました。

${("pojo." + col.name)?eval}
于 2010-04-29T13:43:28.857 に答える