网站首页 > java教程 正文
1.简介
在本篇文章中,我们将研究Handlebars.java库以用于模板管理。
2. maven依赖
让我们从添加handlebars依赖开始:
<dependency> <groupId>com.github.jknack</groupId> <artifactId>handlebars</artifactId> <version>4.1.2</version> </dependency>
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<String, String> 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<Person> 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}} <h4>I live in {{street}}</h4> {{/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<h4>I live in World</h4>\n"); }
我们正在编译模板并将Person实例指定为上下文对象。请注意Person类具有Address字段。这是我们为with助手提供的字段。
虽然我们在上下文对象中进入了一个层次,但如果上下文对象具有多层次嵌套,则更深入。
5.2.each助手
each助手遍历集合:
{{#each friends}} <span>{{name}} is my friend.</span> {{/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("\n<span>Java is my friend.</span>\n" + "\n<span>Spring is my friend.</span>\n"); }
在该示例中,我们将两个Person实例分配给上下文对象的friends字段。因此,最终Handlebars输出两次重复HTML部分。
5.3. if 助手
最后,if助手提供条件渲染。
{{#if busy}} <h4>{{name}} is busy.</h4> {{else}} <h4>{{name}} is not busy.</h4> {{/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<h4>Baeldung is busy.</h4>\n"); }
模板编译后,我们设置上下文对象。由于busy字段为true,因此最终输出
Baeldung is busy.
6. 自定义模板助手
我们还可以创建自己的自定义助手。
6.1. Helper
Helper接口使我们能够创建模板助手。
第一步,我们必须实现Helper:
new Helper<Person>() { @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<Person>() { @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.模板包含
模板包含是重用模板的方法之一。它有利于模板的组成
<h4>Hi {{name}}!</h4>
这是标题模板的内容 - header.html。
为了在另一个模板中使用它,我们必须引用标题模板。
{{>header}} <p>This is the page {{name}}</p>
我们使用页面模板 - 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("<h4>Hi Baeldung!</h4>\n<p>This is the page Baeldung</p>"); }
7.2.模板继承
作为组合的替代,Handlebars提供模板继承.
我们可以使用{{#block}}和{{#partial}}标记来实现继承关系:
<html> <body> {{#block "intro"}} This is the intro {{/block}} {{#block "message"}} {{/block}} </body> </html>
通过这样做,我们看到消息库模板有两块 - 介绍和消息。
要应用继承,我们需要使用{{#partial}}覆盖模板中的这些块:
{{#partial "message" }} Hi there! {{/partial}} {{> messagebase}}
这是simplemessage模板。请注意,我们包含了消息库模板,并且还覆盖了消息块。
8.总结
在本篇文章中,我们了解了Handlebars.java来创建和管理模板。
我们从基本标记用法开始,然后查看加载Handlebars模板的不同选项。
我们还研究了提供大量功能的模板助手。最后,我们研究了重用模板的不同方法。
最后,在GitHub上查看所有示例的源代码。
猜你喜欢
- 2024-10-14 开发者必备:10款最佳JavaScript模板引擎
- 2024-10-14 JNPF一键生成java项目,一款极为好用的java代码生成器
- 2024-10-14 使用C#实现自己的模板引擎(使用c#实现自己的模板引擎功能)
- 2024-10-14 Java web开发:分享Java模板引擎,类似JS语法简单易学(Beetl)
- 2024-10-14 软件更新丨FreeMarker 2.3.29 发布,Java 模板引擎
- 2024-10-14 吐槽java的模板引擎(模板 java)
- 2024-10-14 详细介绍一下SpringBoot的模板引擎技术?
- 2024-10-14 服务器端模板引擎art-template的下载和使用
- 2024-10-14 Java 极轻量级模板引擎 Enjoy(java轻量级组件)
- 2024-10-14 新一代 Java 模板引擎典范 Beetl(java模板引擎性能对比)
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)