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

Handlebars : 不包含逻辑和语义的 Java 模板引擎1 简介在本篇文章中 我们将研究 Handlebars java 库以用于模板管理 2 maven 依赖让我们从添加 handlebars 依赖开始 dependency groupId com github groupId dependency

大家好,欢迎来到IT知识分享网。

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上查看所有示例的源代码。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/90630.html

(0)
上一篇 2026-03-28 16:26
下一篇 2026-03-28 18:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信