O Rocker é um Java 8+ otimizado, perto de renderização de cópia zero, motor de modelo rápido que produz modelos de objetos Java com tampos estaticamente digitados estaticamente que são compilados junto com o restante do seu projeto. Não há mais tempo de "aquecimento" na produção, lógica lenta baseada em reflexão ou surpresas desagradáveis que deveriam ter sido capturadas durante o desenvolvimento.
Escreva seus modelos usando uma sintaxe intuitiva e sem tag com expressões Java padrão para lógica, iteração e valores. Use o Rocker's Special ?
Operador de presença para avaliação nula segura. Todo o levantamento pesado é feito pelo analisador de balancim durante o desenvolvimento - que mantém as dependências de tempo de execução em apenas um punhado de classes. O roqueiro analisará seus modelos e gerará arquivos de origem Java bem documentados (para que você possa inspecionar e entender facilmente como ele funciona).
Inclui os seguintes recursos:
?
O operador de presença estende a sintaxe para manuseio simplificado de valores nulos.Projeto da Fizzed, Inc. (siga no Twitter: @fizzed_inc)
Desenvolver e manter projetos OpenSource requer tempo significativo. Se você achar esse projeto útil ou precisar de suporte comercial, gostaríamos de conversar. Envie -nos um e -mail para [email protected]
Os patrocinadores do projeto podem incluir os seguintes benefícios:
Com base no seguinte benchmark de modelo, o Rocker é o vencedor claro. ~ 250% mais rápido que o Freemarker, além de exigir pedidos de magnitude menos memória.
A maioria dos modelos é usada para sites, então aqui está uma amostra rápida mostrando como os modelos de roqueiros funcionam e podem se chamar durante o processo de renderização. Crie um modelo contendo um cabeçalho e rodapé comum, bem como um espaço reservado para o conteúdo do corpo. Criar modelo src/main/java/views/main.rocker.html
@args (String title, RockerBody content)
< html >
< head >
< title > @title </ title >
</ head >
< body >
@content
</ body >
</ html >
O modelo que realmente planejamos mostrar a um usuário renderizará seu conteúdo no contexto do rodapé comum/cabeçalho. Em termos de Java, está passando um bloco de renderização a ser executado em outro modelo. Criar modelo src/main/java/views/index.rocker.html
@args (String message)
@views.main.template("Home") - > {
< h1 > Hello @message! </ h1 >
}
Ei, e o argumento RockerBody content
? Nós o cobrimos com mais detalhes no readme da sintaxe, mas por enquanto entendemos que é o único tipo especial de argumento e instrui o roqueiro que um modelo espera que um "corpo" seja transmitido a ele.
O analisador de roqueiro gerará um arquivo de origem Java para cada modelo. Eles serão target/generated-sources/rocker/views/main.java
e target/generated-sources/rocker/views/index.java
. No seu aplicativo, você pode renderizar o modelo de índice como assim.
static public void main ( String [] args ) {
String output = views . index . template ( "World" )
. render ()
. toString ();
}
A saída será igual:
< html >
< head >
< title > Home </ title >
</ head >
< body >
< h1 > Hello World! </ h1 >
</ body >
</ html >
Depois de gerar as fontes Java e espiar dentro do código, é simples ver como isso funciona. A classe Views.Index cria uma instância do modelo de visualizações. Main e as mãos se renderizam - além de passar um bloco de si mesmo que ele renderizará quando as @content
. A sintaxe é idêntica à forma como um lambda é definido no Java 8 (implementado com lambdas para Java 8 e classes internas anônimas para Java 6/7). O roqueiro faz várias coisas nos bastidores para garantir que os modelos que criem outros modelos compartilhem o mesmo contexto de renderização (buffer de saída, contexto específico do aplicativo/estado implícito).
Confira o arquivo sintaxe.md para um mergulho profundo abrangente na sintaxe do balancim.
O roqueiro possui uma lista crescente de estruturas com as quais foi perfeitamente integrada. Se você deseja vincular a uma nova estrutura adicionada, registre um problema ou envie um PR:
Estático (texto simples) para cada modelo de balancim é (por padrão) armazenado internamente como matrizes de bytes estáticas já convertidas em seu charset alvo (por exemplo, UTF-8). Quando um modelo é renderizado - as matrizes de bytes estáticas são reutilizadas em todas as solicitações. O balancim renderiza um fluxo de saída otimizado que armazena uma visualização composta (lista vinculada) das matrizes de bytes reutilizadas mais seu conteúdo dinâmico. Como os modelos consistem principalmente em conteúdo estático renderizado no mesmo charset repetidamente, em vez de alocar nova memória, copiar esse conteúdo e depois convertê -lo em seu charset de destino para cada solicitação - o roqueiro simplesmente usa um ponteiro para ele repetidamente de novo. Essa técnica produz renderizações rápidas e com eficiência de memória.
Digamos que você tenha um modelo composto por 9000 bytes de texto estático simples e 1000 bytes de conteúdo dinâmico. Sem essa otimização, exigiria ~ 100 MB de memória para atender 10000 solicitações (10000 bytes x 10000 solicitações). Com essa otimização, exigiria ~ 10 MB de memória para atender 10000 solicitações (1000 bytes x 10000 solicitações). Além da memória mais baixa, você também cortou 90 MB de cópias de memória e 90 MB de String UTF-8> conversões de bytes. Uma otimização bastante útil.
Tudo é compilado pelo compilador do seu projeto, juntamente com o seu outro código -fonte Java. Qualquer código dinâmico em seu modelo é finalmente convertido em Java padrão e compilado. Nenhuma reflexão usada.
Versão 0.10.0 Introduziu o suporte para modelos de recarga a quente durante o desenvolvimento. A recarga a quente permite que você modifique o código -fonte do modelo, salve -o e tenha as alterações ativas na próxima solicitação - sem precisar reiniciar sua JVM. O roqueiro oferece dois sabores diferentes de recarregamento a quente para flexibilidade.
A principal característica dos modelos de roqueiros é que seus modelos são verificados no tempo de compilação para uso, argumentos, lógica etc. pelo compilador Java.
Na versão 0.10.0, a estrutura subjacente de um modelo foi modificada onde um modelo gera duas classes subjacentes. Cada modelo gera uma classe modelo (sua interface) e uma classe de implementação (seu renderizador). Seu aplicativo só interagirá diretamente com o modelo, permitindo que o roqueiro recomponha dinamicamente e recarregue a classe de implementação.
O principal benefício do sabor é que o código do seu aplicativo permanece o mesmo e é verificado pelo compilador Java, enquanto o conteúdo do modelo pode ser modificado e recarregado automaticamente em tempo de execução. Somente no caso em que você realmente altera os argumentos do modelo, você precisará reiniciar seu aplicativo.
Se você preferir a conveniência de modelos totalmente dinâmicos, o sabor dois suporta recarregar a quente da classe Model Model (sua interface) e da classe de implementação (seu renderizador). Seu aplicativo perderá parte da verificação do tempo de compilação e um pequeno sucesso de desempenho, mas obterá a conveniência de tudo ser recarregado. A maneira como seu aplicativo usará modelos também é diferente.
import com . fizzed . rocker . Rocker
...
// dynamic interfaces, dynamic implementation
String rendered = Rocker . template ( "views/index.rocker.html" )
. bind ( "val" , "ValueA" )
. render ()
. toString ();
O caminho do modelo e os argumentos serão verificados no tempo de execução. Observe que cada valor vinculável deve corresponder ao nome e tipo declarados em seu modelo.
Caso seu mapa vinculável possa conter mais valores que os necessários, uma ligação relaxada está disponível. A alternativa relaxada não falhará se um atributo for extra para a lista necessária. Por exemplo:
@args (String name)
Hello ${name}!
Renderá no modo relaxado como:
Map map = new HashMap ();
map . put ( "name" , "Joe" );
map . put ( "age" , 42 );
Rocker . template ( "views/hello.rocker.html" )
. relaxedBind ( map )
. render ();
// -> Hello Joe!
O suporte à recarga a quente é adicionado aos seus modelos gerados por padrão na versão 0.10.0. Se você deseja desativar o suporte, defina o rocker.optimize
de configuração/sistema. Como o código está presente em seus modelos por padrão, você apenas precisa ativá -lo em tempo de execução.
A dependência rocker-compiler
precisa ser adicionada à sua construção. Essa dependência só precisa estar presente durante o desenvolvimento e pode ser removida na produção. Em Maven, isso significa que você deseja adicionar a dependência no escopo provided
.
< dependency >
< groupId >com.fizzed</ groupId >
< artifactId >rocker-compiler</ artifactId >
< version >2.1.0</ version >
< scope >provided</ scope >
</ dependency >
Ative a recarga quente em tempo de execução. Você pode ativar a recarga a quente com uma propriedade do sistema ou programaticamente. Para ativar a recarga a quente com uma propriedade do sistema no Maven.
mvn -Drocker.reloading=true ...rest of args...
Como alternativa, você pode ativar a recarga a quente programaticamente.
import com . fizzed . rocker . runtime . RockerRuntime
...
RockerRuntime . getInstance (). setReloading ( true );
Há um exemplo simples demonstrando recarregamento a quente em ação. Este projeto usa o Blaze para ajudar as tarefas de script. Execute o seguinte
java -jar blaze.jar hot_reload
Aponte seu navegador para http: // localhost: 8080
Em seguida, modifique e salve rocker-test-reload/src/test/java/views/index.rocker.html
e atualize o navegador.
O roqueiro consiste em dois componentes - o analisador/gerador e o tempo de execução. Para usar o Rocker em seu projeto, adicione a dependência do tempo de execução ao seu aplicativo e ative o analisador em sua ferramenta de construção, seguida pela criação do seu primeiro modelo.
O roqueiro é publicado no Maven Central. Para adicionar como uma dependência no Maven:
< dependency >
< groupId >com.fizzed</ groupId >
< artifactId >rocker-runtime</ artifactId >
< version >2.1.0</ version >
</ dependency >
<!-- for hot-reloading support only during development -->
< dependency >
< groupId >com.fizzed</ groupId >
< artifactId >rocker-compiler</ artifactId >
< version >2.1.0</ version >
< scope >provided</ scope >
</ dependency >
Para adicionar como uma dependência em Gradle:
repositories {
mavenCentral()
}
dependencies {
compile group : ' com.fizzed ' , name : ' rocker-runtime ' , version : ' 2.1.0 '
// add rocker-compiler dependency as needed
}
O roqueiro suporta o Maven e o Gradle Out-The of the Box.
Adicione o seguinte ao seu pom
< build >
< plugins >
< plugin >
< groupId >com.fizzed</ groupId >
< artifactId >rocker-maven-plugin</ artifactId >
< version >2.1.0</ version >
< executions >
< execution >
< id >generate-rocker-templates</ id >
< phase >generate-sources</ phase >
< goals >
< goal >generate</ goal >
</ goals >
</ execution >
</ executions >
</ plugin >
</ plugins >
</ build >
Por padrão, o Rocker processará recursivamente quaisquer arquivos de modelo terminando com .rocker.html
em src/main/java
. O diretório O modelo é salvo se tornará o pacote Java padrão em que as classes Java geradas serão colocadas. Os arquivos de origem Java gerados serão salvos para target/generated-sources/rocker
. O plug -in cuidará de adicionar este diretório gerado à raiz de suas fontes.
As seguintes propriedades são suportadas:
templateDirectory
é o diretório base para começar recursivamente ao localizar e analisar arquivos de modelos. O package
Java que um modelo será gerado para usar esse diretório como base. Portanto, se você possui ${templateDirectory}/views/mytemplate.rocker.html
, o rocker gerará ${outputDirectory}/views/mytemplate.java
. Padrão para ${project.build.sourceDirectory}
.
outputDirectory
é o diretório que o analisador gerará fontes para modelos. Padrão para ${project.build.directory}/generated-sources/rocker
classDirectory
é o diretório que o recurso de recarga quente será (re) aulas de compilação para tempo de execução. Padrão para ${project.build.outputDirectory}
failOnError
determina se algum erro de análise/geração faz com que o MAVEN falhe. Padrões para True.
skip
determina se a execução do plug -in deve ser ignorada. Padrões para false.
touchFile
é o arquivo para "tocar" depois de gerar com sucesso as fontes Java. Útil para desencadear outro fluxo de trabalho. Muitos IDEs não recarregarão automaticamente fontes geradas para a conclusão do código, a menos que sejam explicitamente instruídos para recarregar ou se o arquivo maven pom.xml for alterado. Assim, esse valor é por padrão definido como ${basedir}/pom.xml
. Geralmente é inofensivo manter isso ativado.
skipTouch
desativa o touchfile. Padrões para false.
addAsSources
adicionará o diretório de saída ao MAVEN como fontes a serem compiladas. Padrões para True.
addAsTestSources
adicionará o diretório de saída ao MAVEN como fontes de teste a serem compiladas. Padrões para false. Se verdadeiro, isso é avaliado antes do Addassources e efetivamente diz ao Maven para compilar seus modelos como código de teste.
As propriedades a seguir também são suportadas, mas é importante entender que essas são essencialmente substituições de passagem para o analisador e todas elas padrão para o valor padrão do roqueiro.
javaVersion
é a versão Java que você gostaria que seus modelos compilem e com o tempo de execução com o tempo. Padrão para a versão Java do JVM executando o Maven (por exemplo, "1.8").
optimize
determina se o suporte a recarregamento a quente será removido dos modelos gerados. Falso por padrão.
extendsClass
é a classe que todas as implementações de modelo devem se estender. Útil para classes intermediárias específicas de aplicativos que você gostaria que todos os modelos estendam. Padrão para o padrão do roqueiro.
extendsModelClass
é a classe que todos os modelos de modelo devem se estender. Útil para classes intermediárias específicas de aplicativos que você gostaria que todos os modelos de modelo estendam. Padrão para o padrão do roqueiro.
plainTextStrategy
é a estratégia usada para incorporar texto simples como parte dos modelos. O padrão é static_byte_arrays_via_unloaded_class, mas se você precisar de compatibilidade com Graalvm, tentaria static_byte_arrays
discardLogicWhitespace
determina se o espaço em branco em modelos que está determinado a fazer apenas uma parte dos blocos de lógica/controle deve ser descartada. Ajuda a tornar o conteúdo renderizado parecer mais profissional, mantendo a sua formatação intacta. Padrão para o padrão do roqueiro.
targetCharset
é o charset de destino para a saída do modelo. Padrão para o padrão do roqueiro.
suffixRegex
é a expressão regular a ser usada para encontrar modelos para analisar. Padrão para o padrão do roqueiro.
markAsGenerated
adiciona uma anotação @Generated às classes geradas. A retenção é de classe para que a anotação possa ser usada por ferramentas que dependem apenas dos arquivos da classe e não no código -fonte. Padrão para o padrão do roqueiro.
Obrigado ao @victory
e @mnlipp
por contribuir com o plug -in gradle. @etiennestuder
também teve um plug -in Gradle alternativo que você pode considerar também. O plugin Gradle do Rocker é publicado no gradle.org. Basta adicionar o seguinte ao seu script de construção:
plugins {
id " com.fizzed.rocker " version " 2.1.0 "
}
sourceSets {
main {
rocker {
srcDir( ' src/main/java ' )
}
}
}
rocker {
// (All settings are shown with their defaults)
//
// Skips building templates all together
skip false
// Base directory for generated java sources, actual target is sub directory
// with the name of the source set. The value is passed through project.file().
outputBaseDirectory = " $b uildDir /generated-src/rocker "
// Base directory for the directory where the hot reload feature
// will (re)compile classes to at runtime (and where `rocker-compiler.conf`
// is generated, which is used by RockerRuntime.getInstance().setReloading(true)).
// The actual target is a sub directory with the name of the source set.
// The value is passed through project.file().
classBaseDirectory = " $b uildDir /classes "
failOnError true
skipTouch true
// must not be empty when skipTouch is equal to false
touchFile " "
javaVersion ' 1.8 '
extendsClass null
extendsModelClass null
optimize null
discardLogicWhitespace null
targetCharset null
suffixRegex null
postProcessing null
markAsGenerated null
}
A sintaxe do modelo é descrita em detalhes abaixo, mas por enquanto crie um novo arquivo em ${templateDirectory}/views/HelloWorld.rocker.html
@*
Example of hello world
*@
@args (String message)
Hello @message!
Hora de compilar seu projeto e começar a usar o modelo. Você pode chamá -lo de Java como assim:
static public void main ( String [] args ) {
String output = views . HelloWorld
. template ( "World" )
. render ()
. toString ();
}
O roqueiro é fortemente otimizado (por padrão) para modelos de saída como matrizes de bytes. O RockerOutput
Padrão que um modelo será renderizado é do tipo com.fizzed.rocker.runtime.ArrayOfByteArraysOutput
. Esta é uma excelente opção para matrizes de bytes ou IO assíncrono. No entanto, a estrutura tem a capacidade de renderização otimizada para strings (ou outras saídas personalizadas).
Para renderizar com eficiência a uma string:
import com . fizzed . rocker . runtime . StringBuilderOutput ;
static public void main ( String [] args ) {
StringBuilderOutput output = views . HelloWorld
. template ( "World" )
. render ( StringBuilderOutput . FACTORY );
String text = output . toString ();
}
Para renderizar com eficiência a um outputstream:
import com . fizzed . rocker . runtime . OutputStreamOutput ;
static public void main ( String [] args ) throws Exception {
final OutputStream os = new FileOutputStream ( new File ( "test" ));
OutputStreamOutput output = views . HelloWorld
. template ( "World" )
. render (( contentType , charsetName ) -> new OutputStreamOutput ( contentType , os , charsetName ));
}
Observe que, se houver uma exceção durante a renderização, o outputStream terá um modelo parcial renderizado (até o ponto da exceção). Na maioria dos casos, seria melhor renderizar o padrão com.fizzed.rocker.runtime.ArrayOfByteArraysOutput
e escrever seu buffer de matrizes de bytes diretamente para o seu outputStream.
Existem inúmeras demos do roqueiro em ação. Desde modelos de análise em um modelo até o envio de resultados assíncronos em um servidor HTTP. Este projeto usa o Blaze para ajudar as tarefas de script. Execute o seguinte para uma lista completa:
java -jar blaze.jar -l
Copyright (c) 2015+ Fizzed, Inc.
Este trabalho é licenciado sob a licença Apache, versão 2.0. Consulte a licença para obter detalhes.