如何在StringTemplate中迭代遍历Java List?

17

我想在StringTemplate中迭代遍历Hibernate查询结果。我一直在寻找例子,但找不到任何相关资料。

你能帮忙吗?谢谢。


2
如果您可以迭代 Java 集合,那么您就可以将结果列表发送到模板引擎并执行。这对于任何模板引擎来说都应该是非常标准的... - Thihara
2个回答

36

语法看起来像:

<items :{ item | <item> }>

在Java中将它们结合起来:

List<String> teams = Arrays.asList("Cats", "Birds", "Turtles");
ST s = new ST( "<teams :{team | <team> }>");
s.add("teams", teams);
System.out.println(s.render());

在这个示例中,我遍历列表并打印出 teams 列表中的每个团队。将要打印的结果如下:

Cats Birds Turtles 
我们可以探索使这种情况发生的语法。在此之前,请记住,在StringTemplate中默认的分隔符是小于号<和大于号>。由于我们没有指定不同的分隔符,所以在我们的示例中将使用<>。更多有关分隔符的信息请查看.
:{ }

这组符号,冒号:和开闭大括号{}可以被理解为“对于每个”的意思。在这个例子中,代码读取的是,在teams中的每个team上打印team。竖线|左侧表示每次迭代将创建的变量。它将保存来自团队列表的当前团队。打印由竖线|右侧的<team>和闭合大括号}左侧组成。竖线|右侧和闭合括号}之前的所有内容都将被评估并打印。

:{ current value | everything in here will be printed }

为了深入探讨这个概念,让我们使用一个更复杂的数据结构。

public class Player {
    private String name;
    private int age;

    public Person(String name, int age) { 
        this.name = name; 
        this.age = age; 
    }
    public int getAge() { return age; }
    public String getName() { return name; }
}

现在我们可以为我们的团队创建几个玩家:

Player[] players = new Player[] {
    new Player("Bill", 29),
    new Player("Steve", 30),
    new Player("Toby", 15)
};

String playerTemplate = "<players:{ player |<player.name> is <player.age> <\\n>}>"
ST s = new ST( playerTemplate  );
s.add("players", Arrays.asList(players));
System.out.println(s.render());

给出一个结果为

Bill is 29
Steve is 30
Toby is 15

有几点需要注意。我们没有直接访问属性age和name。ST调用了getAge和getName方法。ST不看属性,而是查找访问方法。

如果我们只想遍历包含另一个列表的列表。我们也可以这样做。 首先,让我们构建数据结构并用一些列表填充它。

List<List<String>> listOfLists = asList(
    asList("One", "Two", "Three"), 
    asList("Four", "Five"), 
    asList("Six", "Seven", "Eight", "Nine")
);

模板将会长成以下这个样子。

<list :{ items |<items :{ item |<item> }><\n>}>

我们的模板在这种情况下只是一个组合。外壳将迭代我们提供的列表。

 <list :{ items |  what we will print   }>

然后对于每个项目,我们将打印出其列表中的项目。

<items :{ item |<item> }>

一旦我们将所有东西组合在一起

String template = "<list :{ items |<items :{ item |<item> }><\\n>}>";
ST st = new ST( template);
st.add("list", listOfLists);
System.out.println(st.render());

我们得到的结果看起来像下面这样。

One Two Three 
Four Five 
Six Seven Eight Nine 

在这个概念的基础上,我们可以创建第二个数据结构,其中包含一个球员列表。这将演示如何在迭代中进行嵌套迭代。

我们需要的第一件事是一个包含列表的数据结构。为此,我们可以为我们的球员创建一个团队。

public class Team {
    private List<Player> players;
    private String name;

    public Team (String name, List<Player> players) {
        this.players = players;
        this.name = name;
    }

    public List<Player> getPlayers() {
        return players;
    }

    public String getName() {
        return name;
    }
}

请注意,我们的团队包含球员。这种构成方式将使我们能够建立两个迭代。

现在我们有了数据结构,让我们将一切放在一起,组成几个带有一些球员的团队。

List<Team> teams = asList(
        new Team("Billings", asList(
                new Player("Bill", 29),
                new Player("Steve", 30),
                new Player("Toby", 15)
        )),
        new Team("Laurel", asList(
                new Player("Chad", 32),
                new Player("Chuck", 29),
                new Player("Will", 24),
                new Player("Ben", 26)
        ))
);

现在让我们创建一个模板并填写一些细节:

String simpleTeamTemplate = "<teams:{ team |<team.name> has <length(team.players)> players<\\n>}>";

ST template = new ST( simpleTeamTemplate );
template.add("teams", teams);

System.out.println(template.render());

那将会被打印出来

Billings has 3 players
Laurel has 4 players

我们简单的模板和之前的第一个模板基本相同。唯一的区别是我们使用了ST提供的内置方法length()在这里查看更多关于函数的信息

让我们增加模板的复杂度,将第二次迭代加入其中。

首先,我们将创建playersTemplate。这与我们之前的playerTemplate模板几乎相同。唯一的区别是我们的球员来自一个teamteam.players

String playersTemplate = "<team.players :{ player |<player.name> is <player.age><\\n>}>";
现在我们将构建第二个包含第一个模板的模板。在这个模板中,我们可以遍历团队,并为每个团队打印出名称、球员数量length(team.players)以及playersTemplate中的所有内容。
String teamTemplate = "<teams:{ team |<team.name> has <length(team.players)> players<\\n>"+playersTemplate+"}>"; 

现在让我们把所有的东西都放在一起。

ST teamsTemplate = new ST( simpleTeamTemplate);
teamsTemplate.add("teams", teams);

System.out.println(teamsTemplate.render());

这将会为我们输出以下内容。

Billings has 3 players
Bill is 29
Steve is 30
Toby is 15
Laurel has 4 players
Chad is 32
Chuck is 29
Will is 24
Ben is 26

现在,你真的不想以这种方式组合你的模板。将字符串拼接在一起以组成模板相当愚蠢。StringTemplate 提供了工具,使部分模板的组合变得非常容易。如果您对组合模板感到好奇,可以在这里了解更多。


如果Cats(例如)是一个类Cats而不是一个字符串,会发生什么?我的意思是,如果列表中可以有另一个列表,那该怎么办?我遇到了解析问题,出现了“没有这样的元素异常”。有人能帮忙吗? - AnirbanDebnath
1
我不确定我能在评论中完全回答你的问题,但我会尝试。如果您正在遍历自己的类,则可以调用getter。例如,假设每个团队都是一个具有getName方法的Team类。我们可以调用<team.name>来调用该方法。“<teams:{team | <team.name> }>”接口Team { public String getName(); } @AnirbanDebnath - Chuck Lowery
1
@AnirbanDebnath 我已经更新示例以回答你的问题。我希望这会有所帮助。 - Chuck Lowery

4
%staffForOrg: {staff|
    <tr>
        <td><a href="#%staff.id%a" class="directory " id="%staff.id%1" onclick="javascript: window.location='StaffInfo.html?id=%staff.id%';">%staff.telephoneNumber%</a></td>

    </tr>
}%

这段代码运行完美。

staffForOrg是我的模型列表。我使用Hibernate检索记录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接