Rocker est un moteur de modèles Java 8+ optimisé, proche de rendu zéro-copie qui produit des modèles d'objets Java à typiquement statiquement compilés avec le reste de votre projet. Plus de temps "d'échauffement" dans la production, la logique basée sur la réflexion lente ou les surprises désagréables qui auraient dû être capturées pendant le développement.
Écrivez vos modèles à l'aide d'une syntaxe intuitive et sans étiquette avec des expressions Java standard pour la logique, l'itération et les valeurs. Utiliser Special's Special ?
Opérateur de présence pour l'évaluation de la sécurité nulle. Tout le levage est fait par le rocker analyseur pendant le développement - ce qui maintient les dépendances d'exécution à une poignée de classes. Rocker analysera vos modèles et générera des fichiers source Java bien documentés (afin que vous puissiez facilement inspecter et comprendre comment cela fonctionne).
Comprend les fonctionnalités suivantes:
?
L'opérateur de présence étend la syntaxe pour une manipulation simplifiée des valeurs nulles.Projet de Fizzed, Inc. (Suivez sur Twitter: @fizzed_inc)
Développer et maintenir des projets OpenSource nécessite beaucoup de temps. Si vous trouvez ce projet utile ou avez besoin d'un support commercial, nous aimerions discuter. Envoyez-nous un e-mail à [email protected]
Les sponsors du projet peuvent inclure les avantages suivants:
Sur la base du modèle de référence suivant, Rocker est le gagnant clair. ~ 250% plus rapide que Freemarker tout en nécessitant également des ordres de magnitude.
La plupart des modèles sont utilisés pour les sites Web, voici donc un échantillon rapide montrant comment les modèles de rocker fonctionnent et peuvent s'appeler les uns les autres pendant le processus de rendu. Créez un modèle contenant un en-tête et un pied de page commun ainsi qu'un espace réservé pour le contenu corporel. Créer un modèle src/main/java/views/main.rocker.html
@args (String title, RockerBody content)
< html >
< head >
< title > @title </ title >
</ head >
< body >
@content
</ body >
</ html >
Le modèle que nous prévoyons réellement de montrer à un utilisateur rendra son contenu dans le contexte du pied de page commun / en-tête. En termes Java, il passe un bloc de code de rendu à exécuter dans un autre modèle. Créer un modèle src/main/java/views/index.rocker.html
@args (String message)
@views.main.template("Home") - > {
< h1 > Hello @message! </ h1 >
}
Hé, qu'en est-il de l'argument RockerBody content
? Nous le couvrons plus en détail dans la syntaxe Readme, mais pour l'instant, comprenons que c'est le seul type d'argument spécial et instruit Rocker qu'un modèle s'attend à ce qu'un "corps" lui soit transmis.
L'analyseur Rocker générera un fichier source Java pour chaque modèle. Ils seront target/generated-sources/rocker/views/main.java
et target/generated-sources/rocker/views/index.java
. Dans votre application, vous pouvez rendre le modèle d'index comme ainsi.
static public void main ( String [] args ) {
String output = views . index . template ( "World" )
. render ()
. toString ();
}
La sortie sera égale:
< html >
< head >
< title > Home </ title >
</ head >
< body >
< h1 > Hello World! </ h1 >
</ body >
</ html >
Une fois que vous avez généré les sources Java et un coup d'œil à l'intérieur du code, il est simple de voir comment cela fonctionne. La @content
Views.Index crée une instance de modèle Views.ain. La syntaxe est identique à la façon dont un lambda est défini dans Java 8 (implémenté avec Lambdas pour Java 8 et des classes intérieures anonymes pour Java 6/7). Rocker fait un certain nombre de choses dans les coulisses pour s'assurer que les modèles qui créent d'autres modèles partagent le même contexte de rendu (tampon de sortie, contexte spécifique à l'application / état implicite).
Découvrez le fichier syntax.md pour une plongée profonde complète sur la syntaxe Rocker.
Rocker a une liste croissante de cadres avec lesquels il a été intégré de manière transparente. Si vous souhaitez créer un lien vers un nouveau framework ajouté, veuillez déposer un problème ou soumettre un PR:
Statique (texte brut) pour chaque modèle de basculeur est (par défaut) stocké en interne sous forme de tableaux d'octets statiques déjà convertis en charme cible (par exemple UTF-8). Lorsqu'un modèle est rendu - les tableaux d'octets statiques sont réutilisés sur toutes les demandes. Rocker se rend à un flux de sortie optimisé qui stocke une vue composite (liste liée) des tableaux d'octets réutilisés plus votre contenu dynamique. Étant donné que les modèles se composent principalement de contenu statique rendu dans le même charset encore et encore, plutôt que d'allouer une nouvelle mémoire, de copier ce contenu, puis de la convertir en votre charme cible pour chaque demande - Rocker utilise simplement un pointeur encore. Cette technique produit des rendus rapides et efficaces en mémoire.
Disons que vous avez un modèle composé de 9 000 octets de texte statique simple et de 1000 octets de contenu dynamique. Sans cette optimisation, il faudrait ~ 100 Mo de mémoire pour servir 10000 demandes (10000 octets x 10000 demandes). Avec cette optimisation, il faudrait ~ 10 Mo de mémoire pour servir 10000 demandes (1000 octets x 10000 demandes). Outre la mémoire inférieure, vous coupez également 90 Mo de copies de mémoire et 90 Mo de conversions UTF-8 String-> octet. Une optimisation assez utile.
Tout est compilé par le compilateur de votre projet avec votre autre code source Java. Tout code dynamique de votre modèle est finalement converti en Java standard et compilé. Aucune réflexion utilisée.
La version 0.10.0 a introduit le support pour les modèles de rechargement chaud pendant le développement. Le rechargement chaud vous permet de modifier le code source du modèle, de l'enregistrer et de faire actif les modifications sur la demande suivante - sans avoir à redémarrer votre JVM. Rocker propose deux saveurs différentes de rechargement chaud pour la flexibilité.
La principale caractéristique des modèles Rocker est que vos modèles sont vérifiés par le temps de compilation, les arguments, la logique, etc. par le compilateur Java.
Dans la version 0.10.0, la structure sous-jacente d'un modèle a été modifiée lorsqu'un modèle génère deux classes sous-jacentes. Chaque modèle génère une classe de modèle (son interface) et une classe d'implémentation (son rendu). Votre application ne fera qu'interagir directement avec le modèle, permettant ainsi à Rocker de recompiler et de recharger dynamiquement la classe d'implémentation.
Le principal avantage de la saveur est que votre code d'application reste le même et est vérifié par le temps de compilation par le compilateur Java, tandis que le contenu du modèle peut être modifié et rechargé automatiquement au moment de l'exécution. Ce n'est que dans le cas où vous modifiez réellement les arguments de modèle, vous devrez redémarrer votre application.
Si vous préférez la commodité des modèles entièrement dynamiques, Savet deux prend en charge le rechargement chaud de la classe de modèle de modèle (son interface) ainsi que la classe d'implémentation (son rendu). Votre application perdra une partie de la vérification du temps de compilation et un petit coup de performance, mais gagnera la commodité de tout ce qui est rechargé. La façon dont votre application utilisera des modèles est également différente.
import com . fizzed . rocker . Rocker
...
// dynamic interfaces, dynamic implementation
String rendered = Rocker . template ( "views/index.rocker.html" )
. bind ( "val" , "ValueA" )
. render ()
. toString ();
Le chemin du modèle et les arguments seront vérifiés. Veuillez noter que chaque valeur liée doit correspondre au nom et au type déclaré dans votre modèle.
Dans le cas où votre carte liée peut contenir plus de valeurs que celles requises, une liaison détendue est disponible. L'alternative détendue n'échouera pas le rendu si un attribut est supplémentaire à la liste requise. Par exemple:
@args (String name)
Hello ${name}!
Rendu en mode détendu comme:
Map map = new HashMap ();
map . put ( "name" , "Joe" );
map . put ( "age" , 42 );
Rocker . template ( "views/hello.rocker.html" )
. relaxedBind ( map )
. render ();
// -> Hello Joe!
La prise en charge du rechargement chaud est ajoutée à vos modèles générés par défaut dans la version 0.10.0. Si vous souhaitez désactiver la prise en charge, définissez la propriété Configuration / Système rocker.optimize
sur true pendant votre version. Étant donné que le code est présent dans vos modèles par défaut, il vous suffit de l'activer lors de l'exécution.
La dépendance rocker-compiler
doit être ajoutée à votre construction. Cette dépendance ne doit être présente que pendant le développement et peut être supprimée en production. Dans Maven, cela signifie que vous voudrez ajouter la dépendance dans la portée provided
.
< dependency >
< groupId >com.fizzed</ groupId >
< artifactId >rocker-compiler</ artifactId >
< version >2.1.0</ version >
< scope >provided</ scope >
</ dependency >
Activez le rechargement chaud au moment de l'exécution. Vous pouvez activer le rechargement chaud avec une propriété système ou par programme. Pour activer le rechargement chaud avec une propriété système à Maven.
mvn -Drocker.reloading=true ...rest of args...
Alternativement, vous pouvez activer le rechargement chaud par programme.
import com . fizzed . rocker . runtime . RockerRuntime
...
RockerRuntime . getInstance (). setReloading ( true );
Il y a un exemple simple démontrant un rechargement chaud en action. Ce projet utilise Blaze pour aider les tâches de script. Exécutez ce qui suit
java -jar blaze.jar hot_reload
Pointez votre navigateur vers http: // localhost: 8080
Modifiez et enregistrez ensuite rocker-test-reload/src/test/java/views/index.rocker.html
et actualisez votre navigateur.
Rocker se compose de deux composants - l'analyseur / générateur et l'exécution. Pour utiliser Rocker dans votre projet, ajoutez la dépendance d'exécution à votre application, puis activez l'analyseur dans votre outil de construction suivi par la création de votre premier modèle.
Rocker est publié à Maven Central. Pour ajouter comme dépendance dans 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 >
Pour ajouter comme dépendance à Gradle:
repositories {
mavenCentral()
}
dependencies {
compile group : ' com.fizzed ' , name : ' rocker-runtime ' , version : ' 2.1.0 '
// add rocker-compiler dependency as needed
}
Rocker soutient Maven et Gradle hors de la boîte.
Ajoutez ce qui suit à votre 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 >
Par défaut, Rocker traitera récursivement tous les fichiers de modèle se terminant par .rocker.html
dans src/main/java
. Le répertoire que le modèle est enregistré deviendra le package Java standard dans lequel les classes Java générées seront placées. Les fichiers source Java générés seront enregistrés sur target/generated-sources/rocker
. Le plugin s'occupera d'ajouter ce répertoire généré à votre racine de sources.
Les propriétés suivantes sont prises en charge:
templateDirectory
est le répertoire de base pour commencer récursivement lors de la localisation et de l'analyse des fichiers de modèle. Le package
Java sur lequel un modèle sera généré utilisera ce répertoire comme base. Donc, si vous avez ${templateDirectory}/views/mytemplate.rocker.html
alors Rocker générera ${outputDirectory}/views/mytemplate.java
. Par défaut est ${project.build.sourceDirectory}
.
outputDirectory
est le répertoire que l'analyseur générera des sources de modèles. Par défaut est ${project.build.directory}/generated-sources/rocker
classDirectory
est le répertoire que la fonction de rechargement chaud compilera (re) les classes de compilation au moment de l'exécution. Par défaut à ${project.build.outputDirectory}
failOnError
détermine si des erreurs d'analyse / génération provoquent l'échec de Maven. Par défaut est vrai.
skip
détermine si l'exécution du plugin doit être ignorée. Par défaut est faux.
touchFile
est le fichier à "toucher" après avoir réussi à générer des sources Java. Utile pour déclencher un autre flux de travail. De nombreux IDE ne rechargeront pas automatiquement les sources générées pour l'achèvement du code, sauf si ni dire explicitement de recharger ou si le fichier maven pom.xml est modifié. Ainsi, cette valeur est par défaut définie sur ${basedir}/pom.xml
. Il est généralement inoffensif de garder cela activé.
skipTouch
désactive le tactile. Par défaut est faux.
addAsSources
ajoutera le DeputDirectory à Maven en tant que sources à compiller. Par défaut est vrai.
addAsTestSources
ajoutera le DIRECTORY de sortie à Maven en tant que sources de test à compiller. Par défaut est faux. Si c'est vrai, cela est évalué avant Addassources et dit efficacement à Maven de compiler vos modèles en tant que code de test.
Les propriétés suivantes sont également prises en charge, mais il est important de comprendre que ce sont essentiellement des remplacements de passe à l'analyseur et ils par défaut par défaut de la valeur par défaut de Rocker.
javaVersion
est la version Java avec laquelle vous aimeriez que vos modèles compilent et compatibles avec vos modèles. Par défaut, la version Java du Maven exécutant JVM (par exemple "1.8").
optimize
détermine si le support de rechargement chaud sera supprimé des modèles générés. False par défaut.
extendsClass
est la classe que toutes les implémentations de modèle doivent étendre. Utile pour les classes intermédiaires spécifiques à l'application que vous souhaitez que tous les modèles étendent. Par défaut est par défaut de Rocker.
extendsModelClass
est la classe que tous les modèles de modèles doivent étendre. Utile pour les classes intermédiaires spécifiques à l'application que vous aimeriez que tous les modèles de modèles à étendre. Par défaut est par défaut de Rocker.
plainTextStrategy
est la stratégie utilisée pour intégrer du texte brut dans le cadre des modèles. La valeur par défaut est statique_byte_arrays_via_unloaded_class mais si vous avez besoin de compatibilité Graalvm, vous essayeriez static_byte_arrays
discardLogicWhitespace
détermine si l'espace blanc dans les modèles qui est déterminé comme une partie des blocs logiques / contrôle doit être jeté. Aide à rendre le contenu rendu plus professionnel, tout en conservant une grande partie de votre formatage intact. Par défaut est par défaut de Rocker.
targetCharset
est le charset cible pour la sortie du modèle. Par défaut est par défaut de Rocker.
suffixRegex
est l'expression régulière à utiliser pour trouver des modèles à analyser. Par défaut est par défaut de Rocker.
markAsGenerated
ajoute une annotation @generated aux classes générées. La rétention est une classe afin que l'annotation puisse être utilisée par des outils qui ne reposent que sur les fichiers de classe et non sur le code source. Par défaut est par défaut de Rocker.
Merci à @victory
et @mnlipp
pour avoir contribué le plugin Gradle. @etiennestuder
avait également un autre plugin Gradle que vous voudrez peut-être également considérer. Le plugin Gradle de Rocker est publié sur Gradle.org. Ajoutez simplement ce qui suit à votre script de construction:
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
}
La syntaxe du modèle est décrite en détail ci-dessous, mais pour l'instant, créez un nouveau fichier dans ${templateDirectory}/views/HelloWorld.rocker.html
@*
Example of hello world
*@
@args (String message)
Hello @message!
Il est temps de compiler votre projet et de commencer à utiliser le modèle. Vous pouvez l'appeler à partir de Java comme tel:
static public void main ( String [] args ) {
String output = views . HelloWorld
. template ( "World" )
. render ()
. toString ();
}
Rocker est fortement optimisé (par défaut) aux modèles de sortie sous forme de tableaux d'octets. Le modèle RockerOutput
par défaut sur lequel un modèle sera rendu est du type com.fizzed.rocker.runtime.ArrayOfByteArraysOutput
. C'est un excellent choix pour les tableaux d'octets ou les IO asynchrones. Cependant, le cadre a la capacité d'un rendu optimisé aux chaînes (ou à d'autres sorties personnalisées).
Pour rendre efficacement à une chaîne:
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 ();
}
Pour rendre efficacement à une sortie de sortie:
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 ));
}
Veuillez noter que s'il y a une exception pendant le rendu, la sortie de sortie aurait un modèle partiel rendu (jusqu'au point de l'exception). Dans la plupart des cas, il serait préférable de rendre à la valeur par défaut com.fizzed.rocker.runtime.ArrayOfByteArraysOutput
et écrivez son tampon de tableaux d'octets directement dans votre sortie de sortie.
Il existe de nombreuses démos de rocker en action. Des modèles d'analyse dans un modèle à l'envoi de résultats de manière asynchrone dans un serveur HTTP. Ce projet utilise Blaze pour aider les tâches de script. Exécutez ce qui suit pour une liste complète:
java -jar blaze.jar -l
Copyright (C) 2015+ Fizzed, Inc.
Ce travail est sous licence Apache, version 2.0. Voir la licence pour plus de détails.