Démarrez le moteur de modèle de vitesse

Le moteur de modèles Velocity vous permet de restituer des données à partir d'applications et de servlets. Principalement utilisé pour développer des sites Web dynamiques basés sur des servlets, la séparation nette du modèle et du code Java de Velocity le rend idéal pour le développement Web MVC. En tant que moteur de modèle général, Velocity convient à de nombreux autres objectifs, tels que la génération de code, la génération et la transformation XML et le traitement de flux textuels. Cet article présente le langage de modèle Velocity (VTL) et fournit des exemples d'utilisation du moteur Velocity, y compris comment générer du contenu Web dans un environnement de servlet Java.

Velocity est un outil de création de modèles open source développé par une communauté internationale de volontaires et hébergé par le projet Jakarta de la Apache Software Foundation. Sur le site Web du projet Jakarta Velocity, où vous pouvez télécharger le code source disponible gratuitement, une communauté d'utilisateurs florissante et croissante est prête à répondre aux questions et à proposer des solutions aux problèmes de modèles courants. Velocity a été inspiré par le projet pionnier WebMacro, un travail pour lequel nous, membres de la communauté Velocity, sommes reconnaissants.

Dans cet article, je présente une brève introduction sur le moteur de modèle Velocity et son langage de modèle, Velocity Template Language (VTL). Je montre également comment utiliser Velocity à travers plusieurs exemples.

Hello World, bien sûr

Aucune explication d'un sujet lié à la programmation ne serait complète sans un exemple Hello World. Toute application utilisant Velocity nécessite deux parties. Le premier est le modèle, qui dans cet exemple est un fichier appelé helloworld.vm:

Bonjour $ name! Bienvenue à Velocity!

Le second est un programme Java correspondant appelé HelloWorld.java:

import java.io.StringWriter; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; public class HelloWorld {public static void main (String [] args) lance Exception {/ * d'abord, récupère et initialise un moteur * / VelocityEngine ve = new VelocityEngine (); ve.init (); / * Ensuite, récupérez le Template * / Template t = ve.getTemplate ("helloworld.vm"); / * créer un contexte et ajouter des données * / VelocityContext context = new VelocityContext (); context.put ("nom", "Monde"); / * rend maintenant le modèle dans un StringWriter * / StringWriter writer = new StringWriter (); t.merge (contexte, écrivain); / * affiche le monde * / System.out.println (writer.toString ()); }}

Maintenant, lorsque vous compilez et exécutez ce programme, vous verrez le résultat:

Bonjour le monde! Bienvenue à Velocity!

C'est un exemple trivial, mais il contient les éléments cruciaux pour vous donner une idée de ce qu'est la création de modèles de vitesse.

Pourquoi devrais-je l'utiliser?

Conçu comme un outil de création de modèles général facile à utiliser, Velocity est utile dans tout domaine d'application Java qui nécessite le formatage et la présentation des données. Vous devez utiliser Velocity pour les raisons suivantes:

  • Il s'adapte à de nombreux domaines d'application
  • Il offre une syntaxe simple et claire pour le concepteur de modèles
  • Il offre un modèle de programmation simple pour le développeur
  • Les modèles et le code étant séparés, vous pouvez les développer et les maintenir indépendamment
  • Le moteur Velocity s'intègre facilement dans n'importe quel environnement d'application Java, en particulier les servlets
  • Velocity permet aux modèles d'accéder à n'importe quelle méthode publique d'objets de données dans le contexte

Le dernier point est important - cela signifie que vous pouvez réutiliser vos classes existantes. Ainsi, les objets que vous souhaitez utiliser dans vos modèles n'ont pas besoin d'être structurés d'une certaine manière, comme les JavaBeans, ou d'implémenter des modes d'E / S ou de cycle de vie spéciaux, tels que les taglibs JSP (JavaServer Pages). La seule exigence est que les méthodes soient publiques. Vous en verrez plus lorsque nous couvrirons le langage du modèle en détail.

L'une des forces de Velocity est qu'elle impose fortement une séparation des responsabilités fonctionnelles au sein de l'application. Pour ce faire, il limite l'accès aux modèles aux objets que le code d'application rend spécifiquement disponibles. Cela signifie que les concepteurs peuvent se concentrer exclusivement sur la présentation des données (la vue) et que le programmeur d'application peut se concentrer sur le contrôle de l'application (le contrôleur) et la logique métier et la gestion des données (le modèle) dans Model-View-Controller (MVC) développement. MVC est un modèle de développement bien accepté qui simplifie à la fois le développement et la maintenance continue des applications sophistiquées.

Où est-ce que je l'utilise?

La vitesse est utilisée avec succès dans:

  • Applications Web basées sur des servlets
  • Génération de code Java et SQL
  • Traitement et transformation XML
  • Traitement de texte, tel que la génération de fichiers RTF

Velocity est le plus souvent utilisé comme moteur de rendu pour le développement d'applications Web basées sur des servlets Java, à la place ou en conjonction avec des JSP et d'autres technologies de rendu. Outre la syntaxe de modèle facile et maintenable, Velocity est utilisé dans le développement Web car son langage de modèle peut manipuler et présenter les données, pas créer des données. Cela décourage la programmation dans les modèles. C'est une bonne chose; il maintient la logique métier et applicative de votre code Java à sa place.

Velocity est bien adapté au développement Web J2EE (Java 2 Platform, Enterprise Edition) car la plate-forme accepte des technologies de sortie autres que JSP. Bien que JSP soit inclus dans la spécification J2EE, J2EE ne nécessite pas son utilisation.

Comment ça marche?

Vous utilisez le même processus général pour créer une application basée sur Velocity que n'importe quelle application. Prenons un exemple plus intéressant que l'application Hello World ci-dessus. Supposons que vous exploitiez une animalerie et que vous souhaitiez générer un e-mail pour annoncer une vente. Tout d'abord, vous devez concevoir l'e-mail, puis développer le modèle et le code en fonction de cette conception.

Considérations au moment de la conception

Vous devez tenir compte de trois éléments pour votre conception:

  • Quelles données inclure dans l'e-mail
  • Quelle forme les éléments de données devraient prendre (par exemple, comme List, Mapou String)
  • Comment appeler ces éléments de données

Pour cet exemple, supposons que vous choisissiez trois animaux à vendre, chacun avec un prix annoncé différent. Vous décidez d'utiliser une carte pour associer le nom de chaque animal et son prix, puis de stocker les trois cartes dans une liste. Vous appelez cette liste petList, le nom de l'animal nameet le prix comme pricesur la carte. Maintenant que vous avez identifié les données pertinentes, leur représentation et les critères de dénomination, vous pouvez écrire le code et la conception du modèle.

Écrire le code et la conception du modèle

Une fois que vous êtes d'accord sur les spécificités des données, Velocity vous permet d'écrire le code et de concevoir le modèle en parallèle. Le concepteur intègre les données dans le contenu de la présentation sans données (comme les images, le texte, etc.) dans le modèle. Dans ce cas, nous écrivons simplement dans le corps de l'e-mail:

$ petList.size () Animaux en solde! Nous sommes fiers d'offrir ces beaux animaux à ces prix incroyables. Ce mois-ci seulement, choisissez parmi: #foreach ($ pet dans $ petList) $ pet.name pour seulement $ pet.price #end Appelez aujourd'hui!

En tant que programmeur, vous devez:

  • Récupérez toutes les données des sources de données - une base de données via JDBC (Java Database Connectivity), un fichier ou simplement quelque chose de calculé
  • Mettez ces données dans le contexte en utilisant les noms convenus
  • Rendre le modèle avec le contexte pour produire une sortie

Vous pouvez vous rappeler de l'exemple Hello World que j'ai appelé la classe VelocityContextle contexte . Modélisé après a java.util.Map, le contexte est un objet qui contient les données fournies par l'application ou le servlet auquel le modèle accède.

For this example, we get all the data from our data sources (in this case, we hardwire it into the code), organize it, and add it to the context:

 /* create our list of maps */ ArrayList list = new ArrayList(); Map map = new HashMap(); map.put("name", "horse"); map.put("price", "00.00"); list.add( map ); map = new HashMap(); map.put("name", "dog"); map.put("price", "9.99"); list.add( map ); map = new HashMap(); map.put("name", "bear"); map.put("price", ".99"); list.add( map ); /* add that list to a VelocityContext */ VelocityContext context = new VelocityContext(); context.put("petList", list); 

It appears we really want to get rid of those bears!

Now, with the data organized and placed in the context and the template ready, we can render the template against the context. Here is the code:

import java.io.StringWriter; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; public class PetStoreEmail { public static void main( String[] args ) throws Exception { /* first, get and initialize an engine */ VelocityEngine ve = new VelocityEngine(); ve.init(); /* organize our data */ ArrayList list = new ArrayList(); Map map = new HashMap(); map.put("name", "horse"); map.put("price", "00.00"); list.add( map ); map = new HashMap(); map.put("name", "dog"); map.put("price", "9.99"); list.add( map ); map = new HashMap(); map.put("name", "bear"); map.put("price", ".99"); list.add( map ); /* add that list to a VelocityContext */ VelocityContext context = new VelocityContext(); context.put("petList", list); /* get the Template */ Template t = ve.getTemplate( "petstoreemail.vm" ); /* now render the template into a Writer */ StringWriter writer = new StringWriter(); t.merge( context, writer ); /* use the output in your email body */ sendEmail( writer.toString() ); } } 

This complete program generates your email body. Because Velocity renders templates into a Writer, you can easily manage the output. In this case, the rendered output went into a String via the StringWriter, but it could easily have gone to a file, a browser, or a BLOB (binary large object) in a database. This is one reason why Velocity integrates so easily into Java applications.

The program output (your email body) looks like this:

 3 Pets on Sale! We are proud to offer these fine pets at these amazing prices. This month only, choose from: horse for only 00.00 dog for only 9.99 bear for only .99 Call Today! 

Velocity Template Language

I've shown Velocity templates for two different examples, but in neither case have I explained what the special markup did (although you could probably guess).

The Velocity Template Language (VTL) is a simple syntax providing two parts: references, a formalism for accessing objects in the context; and directives, a set of statements used for control and action. Described as "a language definition with a feature set that fits comfortably on a standard business card" (see Jim Jagielski's "Getting Up to Speed with Velocity") VTL has been intentionally kept simple and small by the community.

References

References in the template access data. They freely mix with the template's non-VTL content. Formally defined, a reference is anything in a template that starts with the '$' character and refers to something in the context. If no corresponding data object exists in the context, the template simply treats the reference as text and renders it as-is into the output stream.

Here is a short template containing a simple reference mixed with non-VTL content:

 Hello $name! Welcome to Velocity! 

Here, the reference is $name. As in the Hello World example, Velocity replaces $name in the template with the toString() return value of what is placed in the context under the key name:

 Hello World! Welcome to Velocity! 

The Velocity reference allows access to any object's public method, and the template's syntax is the same as it would be in Java code. Here are a few examples:

 There are $myBean.getSize() elements. $myObject.anotherMethod( 1, "more data ") $foo.getBar().barMethod("hello", $moredata ) $foo.myMethod( $bar.callThis() ) 

You may recall from the Pet Store email example that we stored the name and price information in a java.util.Map, and accessed the data using two tokens name and price, which don't exist as methods in the java.util.Map class:

 $pet.name for only $pet.price 

This works because Velocity incorporates a JavaBean-like introspection mechanism that lets you express method accesses in references using a property notation. In the Pet Store example template, Velocity's introspection facility finds and invokes the Map's public Object get(String) method with the keys name and price. We could access the same data in a different way by invoking the get(String) method directly in the template:

 $pet.get('name') for only $pet.get('price') 

Cela produirait le même résultat et représenterait mieux ce qui se passe réellement. Cependant, l'autre façon d'utiliser la notation de propriété est plus facile à lire et ne lie pas votre modèle à l'implémentation spécifique de la classe de données. Par exemple, vous pouvez remplacer Mapin the Listpar une classe qui a des méthodes publiques getName()et getPrice(), et l'exemple de modèle d'origine contenant les éléments suivants continuera à fonctionner:

 $ pet.name pour seulement $ pet.price