Mustache.java 的设计目的不是允许不受信任的各方提供模板。可以将其锁定以安全地提供此服务,但默认情况下它是不安全的。使用 SafeMustacheFactory 并将所有模板和部分列入白名单。
从版本 0.9.0 开始,mustache.java 现在仅适用于 Java 8。对于 Java 6/7 支持,请使用 0.8.x。
没有外部依赖项,编译器库约为 100k。
Mustache.java是 Mustache.js 的衍生版本。
有一个用于支持和提问的 Google 群组:http://groups.google.com/group/mustachejava
Github CI:https://github.com/spullara/mustache.java/actions/workflows/maven.yml
API文档:http://spullara.github.io/mustache/apidocs/
Mustache.java 最大的生产部署:
感谢 YourKit 的许多性能改进:
YourKit 以其全功能的 Java Profiler 热忱支持 Mustache.java 开源项目。 YourKit, LLC 是用于分析 Java 和 .NET 应用程序的创新智能工具的创建者。看看YourKit领先的软件产品:
捐款请求:
文档:
mustache
规范测试模空白差异Iterable
都可以用于类似列表的行为ExecutorService
则返回Callable
允许并发评估{{<super}}{{$content}}...{{/content}}{{/super}}
){{#func1}}...{{/func1}}
)是使用 Java 8 中的Function
实现的(替换后)TemplateFunction
handlebar
服务器将渲染模板+json数据,以便设计师快速制作模板模型CapturingMustacheVisitor
从实时系统中提取示例数据进行模拟和测试invert
调用可以采用文本和模板并求解数据表现:
compiler
模块中的com.github.mustachejavabenchmarks
包indy
模块使用 codegen 模块和 invokedynamic 将模板编译为字节码构建建议:
Maven 依赖信息(即,对于大多数常见情况,您只需要compiler
模块):
Java 8+:
< dependency >
< groupId >com.github.spullara.mustache.java</ groupId >
< artifactId >compiler</ artifactId >
< version >0.9.10</ version >
</ dependency >
Java 6/7:
< dependency >
< groupId >com.github.spullara.mustache.java</ groupId >
< artifactId >compiler</ artifactId >
< version >0.8.18</ version >
</ dependency >
模板文件示例:
{{#items}}
Name: {{name}}
Price: {{price}}
{{#features}}
Feature: {{description}}
{{/features}}
{{/items}}
可能由一些支持代码提供支持:
public class Context {
List < Item > items () {
return Arrays . asList (
new Item ( "Item 1" , "$19.99" , Arrays . asList ( new Feature ( "New!" ), new Feature ( "Awesome!" ))),
new Item ( "Item 2" , "$29.99" , Arrays . asList ( new Feature ( "Old." ), new Feature ( "Ugly." )))
);
}
static class Item {
Item ( String name , String price , List < Feature > features ) {
this . name = name ;
this . price = price ;
this . features = features ;
}
String name , price ;
List < Feature > features ;
}
static class Feature {
Feature ( String description ) {
this . description = description ;
}
String description ;
}
}
并会导致:
Name: Item 1
Price: $19.99
Feature: New!
Feature: Awesome!
Name: Item 2
Price: $29.99
Feature: Old.
Feature: Ugly.
模板的评估连续进行。例如,如果您的回调之一中有阻塞代码,系统将在执行它们时暂停:
static class Feature {
Feature ( String description ) {
this . description = description ;
}
String description () throws InterruptedException {
Thread . sleep ( 1000 );
return description ;
}
}
如果您更改描述以返回Callable
,如果您在创建MustacheFactory
时提供了ExecutorService
它将自动在单独的线程中执行。
Callable < String > description () throws InterruptedException {
return new Callable < String >() {
@ Override
public String call () throws Exception {
Thread . sleep ( 1000 );
return description ;
}
};
}
这支持计划任务、流行为和异步 I/O。查看example
模块以查看完整的端到端示例:
package mustachejava ;
import com . github . mustachejava . DefaultMustacheFactory ;
import com . github . mustachejava . Mustache ;
import com . github . mustachejava . MustacheFactory ;
import java . io . IOException ;
import java . io . PrintWriter ;
import java . io . Writer ;
import java . util . Arrays ;
import java . util . List ;
public class Example {
List < Item > items () {
return Arrays . asList (
new Item ( "Item 1" , "$19.99" , Arrays . asList ( new Feature ( "New!" ), new Feature ( "Awesome!" ))),
new Item ( "Item 2" , "$29.99" , Arrays . asList ( new Feature ( "Old." ), new Feature ( "Ugly." )))
);
}
static class Item {
Item ( String name , String price , List < Feature > features ) {
this . name = name ;
this . price = price ;
this . features = features ;
}
String name , price ;
List < Feature > features ;
}
static class Feature {
Feature ( String description ) {
this . description = description ;
}
String description ;
}
public static void main ( String [] args ) throws IOException {
MustacheFactory mf = new DefaultMustacheFactory ();
Mustache mustache = mf . compile ( "template.mustache" );
mustache . execute ( new PrintWriter ( System . out ), new Example ()). flush ();
}
}
提供变量的另一种方法是使用 Map 对象,例如:
public static void main ( String [] args ) throws IOException {
HashMap < String , Object > scopes = new HashMap < String , Object >();
scopes . put ( "name" , "Mustache" );
scopes . put ( "feature" , new Feature ( "Perfect!" ));
Writer writer = new OutputStreamWriter ( System . out );
MustacheFactory mf = new DefaultMustacheFactory ();
Mustache mustache = mf . compile ( new StringReader ( "{{name}}, {{feature.description}}!" ), "example" );
mustache . execute ( writer , scopes );
writer . flush ();
}