Mustache.java não foi projetado para permitir que partes não confiáveis forneçam modelos. Pode ser possível bloqueá-lo para fornecer isso com segurança, mas por padrão é INSEGURO. Use o SafeMustacheFactory e coloque na lista de permissões todos os modelos e parciais.
A partir da versão 0.9.0, mustache.java agora é apenas Java 8. Para suporte Java 6/7, use 0.8.x.
Não há dependências externas e a biblioteca do compilador tem aproximadamente 100k.
Moustache.java é um derivado de bigode.js.
Existe um Grupo do Google para suporte e perguntas: http://groups.google.com/group/mustachejava
CI do Github: https://github.com/spullara/mustache.java/actions/workflows/maven.yml
Documentação da API: http://spullara.github.io/mustache/apidocs/
Maior implantação de produção do Mustache.java:
Obrigado ao YourKit por muitas melhorias de desempenho:
YourKit gentilmente apoia o projeto de código aberto mustache.java com seu Java Profiler completo. YourKit, LLC é criadora de ferramentas inovadoras e inteligentes para criação de perfil de aplicativos Java e .NET. Dê uma olhada nos principais produtos de software do YourKit:
Pedido de contribuições:
Documentação:
mustache
módulo diferenças de espaço em brancoIterable
pode ser usado para comportamentos semelhantes a listasCallable
permite avaliação simultânea se um ExecutorService
estiver configurado{{<super}}{{$content}}...{{/content}}{{/super}}
){{#func1}}...{{/func1}}
) são implementadas usando Function
do Java 8 (pós-substituição)TemplateFunction
se desejar que mustache.java analise novamente os resultados de sua função/lambda (pré-substituição)handlebar
renderizará modelos + dados json para modelos rápidos de modelos feitos por designersCapturingMustacheVisitor
para simulações e testesinvert
pode pegar texto e um modelo e resolver os dadosDesempenho:
com.github.mustachejavabenchmarks
no módulo compiler
indy
usa o módulo codegen e invoquedynamic para compilar modelos até bytecodeSugestões de construção:
Informações de dependência do Maven (ou seja, para os casos mais comuns, você precisará apenas do 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 >
Exemplo de arquivo de modelo:
{{#items}}
Name: {{name}}
Price: {{price}}
{{#features}}
Feature: {{description}}
{{/features}}
{{/items}}
Pode ser alimentado por algum código de apoio:
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 ;
}
}
E resultaria em:
Name: Item 1
Price: $19.99
Feature: New!
Feature: Awesome!
Name: Item 2
Price: $29.99
Feature: Old.
Feature: Ugly.
A avaliação do modelo ocorre em série. Por exemplo, se você tiver código de bloqueio em um de seus retornos de chamada, o sistema irá pausar enquanto os executa:
static class Feature {
Feature ( String description ) {
this . description = description ;
}
String description () throws InterruptedException {
Thread . sleep ( 1000 );
return description ;
}
}
Se você alterar a descrição para retornar um Callable
, ele será executado automaticamente em um thread separado se você tiver fornecido um ExecutorService
ao criar seu MustacheFactory
.
Callable < String > description () throws InterruptedException {
return new Callable < String >() {
@ Override
public String call () throws Exception {
Thread . sleep ( 1000 );
return description ;
}
};
}
Isso permite tarefas agendadas, comportamento de streaming e E/S assíncrona. Confira o módulo example
para ver um exemplo completo de ponta a ponta:
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 ();
}
}
Uma abordagem alternativa para fornecer variáveis seria usar um 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 ();
}