使用单个freemarker模板显示任意pojos的表 [英] Use a single freemarker template to display tables of arbitrary pojos
问题描述
关注高级Freemarker专家:
Attention advanced Freemarker gurus:
我想使用一个freemarker模板来输出任意pojos的表,其中要显示的列与数据分开定义.问题是我无法弄清楚如何在运行时在pojo上获取函数的句柄,然后让freemarker调用该函数(lambda样式).从文档上看,Freemarker似乎支持函数式编程,但是我似乎无法将适当的咒语区分开来.
I want to use a single freemarker template to be able to output tables of arbitrary pojos, with the columns to display defined separately than the data. The problem is that I can't figure out how to get a handle to a function on a pojo at runtime, and then have freemarker invoke that function (lambda style). From skimming the docs it seems that Freemarker supports functional programming, but I can't seem to forumulate the proper incantation.
我举了一个简单的具体例子.假设我有两个列表:一个具有firstName和lastName的人员列表,以及一个具有品牌和型号的汽车列表.想要输出这两个表:
I whipped up a simplistic concrete example. Let's say I have two lists: a list of people with a firstName and lastName, and a list of cars with a make and model. would like to output these two tables:
<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类型的框架的一部分.
But I want to use the same template, since this is part of a framework that has to deal with dozens of different pojo types.
给出以下代码:
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();
}
}
以上所有都是针对此问题的.这是我一直在研究的模板.记下我遇到麻烦的评论.
All the above is a given for this problem. So here is the template I have been hacking on. Note the comment where I am having trouble.
<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访问的属性的名称.我尝试了一些事情,例如
So col.name has the name of the property I want to access from the pojo. I have tried a few things, such as
pojo.col.name
和
<#assign property = col.name/>
${pojo.property}
但是这些当然是行不通的,我只是将它们包括在内以帮助传达我的意图.我正在寻找一种获取函数句柄并让freemarker调用它的方法,或者某种评估"功能,可以将任意表达式作为字符串并在运行时对其进行评估.
but of course these don't work, I just included them to help convey my intent. I am looking for a way to get a handle to a function and have freemarker invoke it, or perhaps some kind of "evaluate" feature that can take an arbitrary expression as a string and evaluate it at runtime.
推荐答案
找到了答案.
${("pojo." + col.name)?eval}
这篇关于使用单个freemarker模板显示任意pojos的表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!