我需要为我的 Scala 项目选择一个 Mustache 渲染引擎。似乎只有 Mustache-Java 和 Scalate 两个选择?有比较吗?两者中哪一个更稳定/性能更好?
5 回答
我刚刚经历了同样的过程(Mustache Scalate 或 Mustache Java)。我最终选择了 Mustache Java,它运行良好。
为什么要使用小胡子 Java?因为我想要的只是 Mustache 模板。Scalate 不仅有这种支持,而且我不想在我的代码库中添加更多“东西”,而只想使用它的部分功能。
我使用 mustache 作为 scalatra-scalate 的一部分。这对我来说是唯一明智的选择,因为我已经投资了 Scalatra。如果可以选择,我会彻底尝试 mustache-java。Scalate 引擎(仍然?)有些古怪和不成熟。
我遇到的几个例子:
- 如果您修改默认分隔符 {{=<% %>=}} 从那时起您将不得不在分隔符周围添加空格,否则解析器会阻塞
- 如果你想为丢失的键插入自定义处理,你会被卡住
- 有时渲染会无缘无故地一次挂起几分钟(这是 Jade,而不是 Mustache,但无论如何它都相当可怕)
如果您不做复杂的事情,mustache 可以正常工作,Scalate 添加了一些漂亮的功能,如默认模板等,这可能会对您有所帮助。
我刚刚经历了这个磨难,因为我使用的是 Scala,所以尽管我想使用 scalate,但我最终使用Mustache-Java有两个原因:
- 没有简单的方法可以从
/resources
类路径中的 dir 加载模板(甚至只是普通的 Java 流对象)。这似乎很基本,我很困惑为什么这不可用 OOB。 - 与 #1 类似,没有简单的方法可以从简单的
String
. 如果你想这样做,你还需要编写一个自定义加载器。为什么?
这是基于他们的文档。如果你用它来生成服务器端的网页,Scalate 看起来非常强大和灵活,但对于简单的用例,它会带来太多的包袱。
我在 Mustache-Java 中发现的一件事是,您需要将数据转换为 Java 映射,否则它不起作用(至少在 Scala 2.12 中):
"Mustache test" should "succeed" in {
import scala.collection.JavaConverters._
val template = "Hello, {{name}}"
val mf = new DefaultMustacheFactory()
val mustache = mf.compile(new StringReader(template), "sample")
val map = Map("name" -> "Joe")
val sw = new StringWriter()
mustache.execute(sw, map.asJava) // if you don't use .asJava here it's not going to work
assert(sw.toString.contains("Joe"))
}
倒置部分工作:
"Mustache test exclusion" should "succeed" in {
import scala.collection.JavaConverters._
val template = "Hello, {{^exclude}}am I excluded?{{/exclude}}"
val mf = new DefaultMustacheFactory()
val mustache = mf.compile(new StringReader(template), "sample")
val map = Map("exclude" -> true)
val sw = new StringWriter()
mustache.execute(sw, map.asJava)
assert(!sw.toString.contains("excluded"))
}
最后,关于列表:支持案例类,但对于任何列表字段,它们必须是 Java 类型。以下变体应该有效:
case class Plan(name: String,
currency: String,
price: String)
"Mustache test with object context with list" should "succeed" in {
import scala.collection.JavaConverters._
import java.util.{List => JavaList}
val template =
"""{{#plans}}
|Name: {{name}}
|Price: {{currency}}{{price}}
|{{/plans}}""".stripMargin
val mf = new DefaultMustacheFactory()
val mustache = mf.compile(new StringReader(template), "sample")
// note the Java list type here
case class Plans(plans: JavaList[Plan])
val plans = Plans(Seq(Plan("essential", "$", "30")).asJava)
val sw = new StringWriter()
mustache.execute(sw, plans)
val list = Seq(Plan("essential", "$", "30")).asJava
mustache.execute(sw, Map("plans" -> list).asJava)
assert(sw.toString.contains("Name"))
}
"Mustache test with list" should "succeed" in {
import scala.collection.JavaConverters._
val template =
"""{{#plans}}
|Name: {{name}}
|Price: {{currency}}{{price}}
|{{/plans}}""".stripMargin
val mf = new DefaultMustacheFactory()
val mustache = mf.compile(new StringReader(template), "sample")
val sw = new StringWriter()
// do not forget .asJava here
val list = Seq(Plan("essential", "$", "30")).asJava
// do not forget .asJava here
mustache.execute(sw, Map("plans" -> list).asJava)
assert(sw.toString.contains("Name"))
}
Mustache-Java 的一个好处是相对于 Scala,Java 的编译速度非常快。
Scalate 使渲染 Mustache 模板变得容易,我宁愿使用相对直观的 Scala 库而不是 Java 库。
假设您有以下simple_example.mustache
模板:
I like {{programming_language}}
The code is {{code_description}}
您可以使用以下代码呈现模板:
import org.fusesource.scalate.TemplateEngine
val sourceDataPath = os.pwd/"simple_example.mustache".toString
val engine = new TemplateEngine
val someAttributes = Map(
"programming_language" -> "Scala",
"code_description" -> "pretty"
)
engine.layout(sourceDataPath, someAttributes)
结果如下:
I like Scala
The code is pretty