gpt4 book ai didi

freemarker - 使用单个 freemarker 模板显示任意 pojo 表

转载 作者:行者123 更新时间:2023-12-04 14:52:33 30 4
gpt4 key购买 nike

注意高级 Freemarker 大师:

我想使用单个 freemarker 模板来输出任意 pojo 的表,其中要显示的列与数据分开定义。问题是我无法弄清楚如何在运行时获取 pojo 上的函数句柄,然后让 freemarker 调用该函数(lambda 样式)。从浏览文档看来,Freemarker 支持函数式编程,但我似乎无法制定正确的咒语。

我举了一个简单的具体例子。假设我有两个列表:一个包含名字和姓氏的人员列表,以及一个包含品牌和型号的汽车列表。想输出这两个表:

<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 调用它,或者可能是某种“评估”功能,它可以将任意表达式作为字符串并在运行时对其进行评估。

最佳答案

?eval (几乎?)总是一个坏主意,因为它通常伴随着性能缺陷(例如大量解析)和安全问题(例如“FTL 注入(inject)”)。

更好的方法是使用方括号语法:

There is an alternative syntax if we want to specify the subvariable name with an expression: book["title"]. In the square brackets you can give any expression as long as it evaluates to a string.



(来自 FreeMarker documentation about retrieving data from a hash)

在你的情况下,我会推荐类似 ${pojo[col.name]} .

关于freemarker - 使用单个 freemarker 模板显示任意 pojo 表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2733446/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com