Moustache.java no está diseñado para permitir que partes que no son de confianza proporcionen plantillas. Es posible bloquearlo para proporcionarlo de forma segura, pero de forma predeterminada NO ES SEGURO. Utilice SafeMustacheFactory y incluya en la lista blanca todas las plantillas y parciales.
A partir de la versión 0.9.0, mustache.java ahora es solo Java 8. Para compatibilidad con Java 6/7, utilice 0.8.x.
No hay dependencias externas y la biblioteca del compilador es de ~100k.
Moustache.java es un derivado de bigote.js.
Hay un grupo de Google para soporte y preguntas: http://groups.google.com/group/mustachejava
CI de Github: https://github.com/spullara/mustache.java/actions/workflows/maven.yml
Documentación API: http://spullara.github.io/mustache/apidocs/
Mayor implementación de producción de Moustache.java:
Gracias a YourKit por muchas mejoras de rendimiento:
YourKit apoya amablemente el proyecto de código abierto mustache.java con su Java Profiler con todas las funciones. YourKit, LLC es el creador de herramientas innovadoras e inteligentes para crear perfiles de aplicaciones Java y .NET. Eche un vistazo a los productos de software líderes de YourKit:
Solicitud de contribuciones:
Documentación:
mustache
, diferencias de módulo de espacios en blancoIterable
se puede utilizar para comportamientos similares a listas.Callable
permite la evaluación simultánea si se configura un ExecutorService
{{<super}}{{$content}}...{{/content}}{{/super}}
){{#func1}}...{{/func1}}
) se implementan utilizando Function
de Java 8 (post-sustitución)TemplateFunction
si desea que mustache.java analice los resultados de su función/lambda (pre-sustitución)handlebar
representará plantillas + datos json para que los diseñadores realicen maquetas rápidas de plantillas.CapturingMustacheVisitor
para simulacros y pruebas.invert
puede tomar texto y una plantilla y resolver los datos.Actuación:
com.github.mustachejavabenchmarks
en el módulo compiler
indy
utiliza el módulo codegen e invokedynamic para compilar plantillas hasta el código de bytes.Sugerencias de construcción:
Información de dependencia de Maven (es decir, para los casos más comunes, solo necesitará el módulo 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 >
Archivo de plantilla de ejemplo:
{{#items}}
Name: {{name}}
Price: {{price}}
{{#features}}
Feature: {{description}}
{{/features}}
{{/items}}
Podría funcionar con algún código de respaldo:
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 ;
}
}
Y resultaría en:
Name: Item 1
Price: $19.99
Feature: New!
Feature: Awesome!
Name: Item 2
Price: $29.99
Feature: Old.
Feature: Ugly.
La evaluación de la plantilla se realiza en serie. Por ejemplo, si tiene un código de bloqueo dentro de una de sus devoluciones de llamada, el sistema se detendrá mientras las ejecuta:
static class Feature {
Feature ( String description ) {
this . description = description ;
}
String description () throws InterruptedException {
Thread . sleep ( 1000 );
return description ;
}
}
Si cambia la descripción para devolver un Callable
, se ejecutará automáticamente en un hilo separado si proporcionó un ExecutorService
cuando creó su MustacheFactory
.
Callable < String > description () throws InterruptedException {
return new Callable < String >() {
@ Override
public String call () throws Exception {
Thread . sleep ( 1000 );
return description ;
}
};
}
Esto permite tareas programadas, comportamiento de transmisión y E/S asincrónicas. Consulte el módulo example
para ver un ejemplo completo de un extremo a otro:
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 ();
}
}
Un enfoque alternativo para proporcionar variables sería utilizar un objeto Map, como:
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 ();
}