ITPub博客

首页 > 应用开发 > > Handlebars : 不包含逻辑和语义的 Java 模板引擎

Handlebars : 不包含逻辑和语义的 Java 模板引擎

作者:micromad 时间:2019-10-22 14:48:31 0 删除 编辑

1.简介

在本篇文章中,我们将研究Handlebars.java库以用于模板管理。

2. maven依赖

让我们从添加handlebars依赖开始:

com.github.jknack

handlebars

4.1.2

3.模板示例

Handlebars模板支持任何类型的文本文件。它由{{name}}和{{#each people}}等标记组成。

然后我们通过传递上下文对象(如Map或其他Object)来填充这些标记。

3.1.使用 this

要将单个String值传递给我们的模板,我们可以使用任何Object作为上下文。我们还必须在模板中使用{{this}}标记。

然后Handlebars在上下文对象上调用toString方法,并用结果替换标记:

@Test

public void whenThereIsNoTemplateFile_ThenCompilesInline() throws IOException {

Handlebars handlebars = new Handlebars();

Template template = handlebars.compileInline("Hi {{this}}!");

String templateString = template.apply("Baeldung");

assertThat(templateString).isEqualTo("Hi Baeldung!");

}

在上面的示例中,我们首先创建Handlebars的实例,即我们的API入口点。

然后,我们为该实例提供模板。在这里,我们只是内联传递模板,但我们在一瞬间看到一些更强大的方法。

最后,我们给编译模板提供了上下文。{{this}}最终会调用toString,这就是我们看到“Hi Baeldung!”的原因。

3.2. 使用将 map 作为上下文对象传递

我们刚刚看到了如何为上下文传递一个String,现在让我们尝试一下Map:

@Test

public void whenParameterMapIsSupplied_thenDisplays() throws IOException {

Handlebars handlebars = new Handlebars();

Template template = handlebars.compileInline("Hi {{name}}!");

Map parameterMap = new HashMap ();

parameterMap.put("name", "Baeldung");

String templateString = template.apply(parameterMap);

assertThat(templateString).isEqualTo("Hi Baeldung!");

}

与前面的示例类似,我们正在编译模板然后传递上下文对象,但这次是使用Map。

另请注意,我们使用的是{{name}}而不是{{this}}。这意味着我们的Map必须包含 key,name。

3.3.传递自定义对象作为上下文对象

我们还可以将自定义对象传递给模板:

public class Person {

private String name;

private boolean busy;

private Address address = new Address();

private List friends = new ArrayList ();

public static class Address {

private String street;

}

}

使用Person类,我们将获得与前一个示例相同的结果:

@Test

public void whenParameterObjectIsSupplied_ThenDisplays() throws IOException {

Handlebars handlebars = new Handlebars();

Template template = handlebars.compileInline("Hi {{name}}!");

Person person = new Person();

person.setName("Baeldung");

String templateString = template.apply(person);

assertThat(templateString).isEqualTo("Hi Baeldung!");

}

我们模板中的{{name}}将深入到Person对象并获取name字段的值。

4.模板加载器

到目前为止,我们已经使用了代码中定义的模板。但是,它不是唯一的选择。我们还可以从文本文件中读取模板。

Handlebars.java为从类路径,文件系统或servlet上下文中读取模板提供了特殊支持。默认情况下,Handlebars会扫描类路径以加载给定的模板:

@Test

public void whenNoLoaderIsGiven_ThenSearchesClasspath() throws IOException {

Handlebars handlebars = new Handlebars();

Template template = handlebars.compile("greeting");

Person person = getPerson("Baeldung");

String templateString = template.apply(person);

assertThat(templateString).isEqualTo("Hi Baeldung!");

}

因此,我们调用了compile而不是compileInline,这也是Handlebars在类路径上查找/greeting.hbs的暗示。

但是,我们也可以使用ClassPathTemplateLoader配置这些属性:

@Test

public void whenClasspathTemplateLoaderIsGiven_ThenSearchesClasspathWithPrefixSuffix() throws IOException {

TemplateLoader loader = new ClassPathTemplateLoader("/handlebars", ".html");

Handlebars handlebars = new Handlebars(loader);

Template template = handlebars.compile("greeting");

// ... same as before

}

在这种情况下,我们告诉Handlebars在类路径上查找/handlebars/greeting.html。

最后,我们可以链接多个TemplateLoader实例:

@Test

public void whenMultipleLoadersAreGiven_ThenSearchesSequentially() throws IOException {

TemplateLoader firstLoader = new ClassPathTemplateLoader("/handlebars", ".html");

TemplateLoader secondLoader = new ClassPathTemplateLoader("/templates", ".html");

Handlebars handlebars = new Handlebars().with(firstLoader, secondLoader);

// ... same as before

}

所以,在这里,我们有两个加载器,这意味着Handlebars将搜索两个目录中的 greeting 模板。

5.内置助手

在编写模板时,内置帮助程序提供了额外的功能。

5.1.with助手

with 助手更改当前上下文:

{{#with address}}

I live in {{street}}

{{/with}}

在我们的示例模板中,{{#with address}}标记开始该部分,{{/with}}}标记结束它。

从本质上讲,我们正在深入研究当前的上下文对象 - 让我们说下 person - 并将地址设置为with部分的本地上下文。此后,本节中的每个字段引用都将由person.address添加。

因此,{{street}}标记将保存person.address.street的值:

@Test

public void whenUsedWith_ThenContextChanges() throws IOException {

Handlebars handlebars = new Handlebars(templateLoader);

Template template = handlebars.compile("with");

Person person = getPerson("Baeldung");

person.getAddress().setStreet("World");

String templateString = template.apply(person);

assertThat(templateString).isEqualTo("\n

I live in World

\n");

}

我们正在编译模板并将Person实例指定为上下文对象。请注意Person类具有Address字段。这是我们为with助手提供的字段。

虽然我们在上下文对象中进入了一个层次,但如果上下文对象具有多层次嵌套,则更深入。

5.2.each助手

each助手遍历集合:

{{#each friends}}

{{name}} is my friend.

{{/each}}

使用{{#each friends}}和{{/each}}作为打开和关闭迭代部分结果的标记,Handlebars将迭代上下文对象的friends字段。

@Test

public void whenUsedEach_ThenIterates() throws IOException {

Handlebars handlebars = new Handlebars(templateLoader);

Template template = handlebars.compile("each");

Person person = getPerson("Baeldung");

Person friend1 = getPerson("Java");

Person friend2 = getPerson("Spring");

person.getFriends().add(friend1);

person.getFriends().add(friend2);

String templateString = template.apply(person);

assertThat(templateString).isEqualTo("\nJava is my friend.\n"

+ "\nSpring is my friend.\n");

}

在该示例中,我们将两个Person实例分配给上下文对象的friends字段。因此,最终Handlebars输出两次重复HTML部分。

5.3. if 助手

最后,if助手提供条件渲染。

{{#if busy}}

{{name}} is busy.

{{else}}

{{name}} is not busy.

{{/if}}

在我们的模板中,我们根据 busy 字段提供不同的消息。

@Test

public void whenUsedIf_ThenPutsCondition() throws IOException {

Handlebars handlebars = new Handlebars(templateLoader);

Template template = handlebars.compile("if");

Person person = getPerson("Baeldung");

person.setBusy(true);

String templateString = template.apply(person);

assertThat(templateString).isEqualTo("\n

Baeldung is busy.

\n");

}

模板编译后,我们设置上下文对象。由于busy字段为true,因此最终输出

Baeldung is busy.

6. 自定义模板助手

我们还可以创建自己的自定义助手。

6.1. Helper

Helper接口使我们能够创建模板助手。

第一步,我们必须实现Helper:

new Helper() {

@Override

public Object apply(Person context, Options options) throws IOException {

String busyString = context.isBusy() ? "busy" : "available";

return context.getName() + " - " + busyString;

}

}

我们可以看到,Helper接口只有一个接受上下文和选项对象的方法。出于我们的目的,我们将输出Person的name和busy字段。

创建 Helper 程序后,我们还必须使用 Handlebars 注册我们的自定义帮助程序:

@Test

public void whenHelperIsCreated_ThenCanRegister() throws IOException {

Handlebars handlebars = new Handlebars(templateLoader);

handlebars.registerHelper("isBusy", new Helper() {

@Override

public Object apply(Person context, Options options) throws IOException {

String busyString = context.isBusy() ? "busy" : "available";

return context.getName() + " - " + busyString;

}

});

// implementation details

}

在我们的示例中,我们使用Handlebars.registerHelper()方法在isBusy的名称下注册我们的helper程序。

作为最后一步,我们必须使用helper程序的名称在模板中定义标记:

{{#isBusy this}}{{/isBusy}}

请注意,每个helper程序都有一个起始和结束标记。

6.2. Helper 方法

当我们使用Helper接口时,我们只能创建一个帮助器。相反,helper类使我们能够定义多个模板助手。而且,我们不需要实现任何特定的接口。我们只是在类中编写helper方法,然后HandleBars使用反射提取helper定义:

public class HelperSource {

public String isBusy(Person context) {

String busyString = context.isBusy() ? "busy" : "available";

return context.getName() + " - " + busyString;

}

// Other helper methods

}

由于helper源可以包含多个helper程序实现,因此与单个helper程序注册不同:

@Test

public void whenHelperSourceIsCreated_ThenCanRegister() throws IOException {

Handlebars handlebars = new Handlebars(templateLoader);

handlebars.registerHelpers(new HelperSource());

// Implementation details

}

我们使用Handlebars.registerHelpers()方法注册我们的助手。此外,helper方法的名称将成为helper程序标记的名称。

7.模板重用

Handlebars库提供了几种重用现有模板的方法。

7.1.模板包含

模板包含是重用模板的方法之一。它有利于模板的组成

Hi {{name}}!

这是标题模板的内容 - header.html。

为了在另一个模板中使用它,我们必须引用标题模板。

{{>header}}

This is the page {{name}}

我们使用页面模板 - page.html - 其中包含使用{{>header}}的标题模板。

当Handlebars.java处理模板时,最终将包含header的内容输出:

@Test

public void whenOtherTemplateIsReferenced_ThenCanReuse() throws IOException {

Handlebars handlebars = new Handlebars(templateLoader);

Template template = handlebars.compile("page");

Person person = new Person();

person.setName("Baeldung");

String templateString = template.apply(person);

assertThat(templateString).isEqualTo("

Hi Baeldung!

\n

This is the page Baeldung

");

}

7.2.模板继承

作为组合的替代,Handlebars提供模板继承.

我们可以使用{{#block}}和{{#partial}}标记来实现继承关系:

{{#block "intro"}}

This is the intro

{{/block}}

{{#block "message"}}

{{/block}}

通过这样做,我们看到消息库模板有两块 - 介绍和消息。

要应用继承,我们需要使用{{#partial}}覆盖模板中的这些块:

{{#partial "message" }}

Hi there!

{{/partial}}

{{> messagebase}}

这是simplemessage模板。请注意,我们包含了消息库模板,并且还覆盖了消息块。

8.总结

在本篇文章中,我们了解了Handlebars.java来创建和管理模板。

我们从基本标记用法开始,然后查看加载Handlebars模板的不同选项。

我们还研究了提供大量功能的模板助手。最后,我们研究了重用模板的不同方法。

最后,在GitHub上查看所有示例的源代码。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2763/viewspace-3131430/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-16

  • 博文量
    75
  • 访问量
    575