Avvia Velocity Template Engine

Velocity Template Engine consente di eseguire il rendering dei dati dall'interno di applicazioni e servlet. Utilizzato principalmente per sviluppare siti Web dinamici e basati su servlet, la netta separazione tra template e codice Java di Velocity lo rende ideale per lo sviluppo Web MVC. Come motore di modelli generali, Velocity si adatta a molti altri scopi, come la generazione di codice, la generazione e la trasformazione XML e l'elaborazione del flusso di testo. Questo articolo introduce il Velocity Template Language (VTL) e fornisce esempi di come utilizzare il motore Velocity, incluso come generare contenuto Web in un ambiente servlet Java.

Velocity è uno strumento di creazione di modelli open source sviluppato da una comunità internazionale di volontari e ospitato dal progetto Jakarta della Apache Software Foundation. Sul sito web del Jakarta Velocity Project, dove è possibile scaricare il codice sorgente disponibile gratuitamente, una fiorente e crescente comunità di utenti è pronta a rispondere alle domande e offrire soluzioni ai comuni problemi di template. Velocity è stato ispirato dal progetto pionieristico WebMacro, un lavoro per il quale noi della community di Velocity siamo grati.

In questo articolo, presento una breve introduzione su Velocity Template Engine e il suo linguaggio di template, Velocity Template Language (VTL). Dimostro anche come usare Velocity attraverso diversi esempi.

Hello World, ovviamente

Nessuna spiegazione di un argomento relativo alla programmazione sarebbe completa senza un esempio Hello World. Qualsiasi applicazione che utilizza Velocity richiede due parti. Il primo è il modello, che in questo esempio è un file chiamato helloworld.vm:

Ciao $ nome! Benvenuto in Velocity!

Il secondo è un programma Java corrispondente chiamato 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) genera Exception {/ * per prima cosa, ottenere e inizializzare un motore * / VelocityEngine ve = new VelocityEngine (); ve.init (); / * successivamente, ottieni il Template * / Template t = ve.getTemplate ("helloworld.vm"); / * crea un contesto e aggiungi dati * / VelocityContext context = new VelocityContext (); context.put ("nome", "Mondo"); / * ora esegue il rendering del modello in uno StringWriter * / StringWriter writer = new StringWriter (); t.merge (contesto, scrittore); / * mostra il mondo * / System.out.println (writer.toString ()); }}

Ora, quando compili ed esegui questo programma, vedrai l'output:

Ciao mondo! Benvenuto in Velocity!

Questo è un esempio banale, ma contiene i pezzi cruciali per darti un'idea di cosa sia il templating di Velocity.

Perché dovrei usarlo?

Progettato come uno strumento generale di facile utilizzo per la creazione di modelli, Velocity è utile in qualsiasi area dell'applicazione Java che richiede la formattazione e la presentazione dei dati. Dovresti usare Velocity per i seguenti motivi:

  • Si adatta a molte aree di applicazione
  • Offre una sintassi semplice e chiara per il progettista di modelli
  • Offre un semplice modello di programmazione per lo sviluppatore
  • Poiché i modelli e il codice sono separati, è possibile svilupparli e mantenerli in modo indipendente
  • Il motore Velocity si integra facilmente in qualsiasi ambiente applicativo Java, in particolare servlet
  • Velocity consente ai modelli di accedere a qualsiasi metodo pubblico di oggetti dati nel contesto

L'ultimo punto è importante: significa che puoi riutilizzare le tue classi esistenti. Quindi, gli oggetti che desideri utilizzare nei tuoi modelli non devono essere strutturati in un certo modo, come JavaBeans, o implementare modalità speciali di I / O o del ciclo di vita, come i tagli JSP (JavaServer Pages). L'unico requisito è che i metodi siano pubblici. Vedrai più di questo quando tratteremo in dettaglio il linguaggio del modello.

Uno dei punti di forza di Velocity è che impone fortemente una separazione delle responsabilità funzionali all'interno dell'applicazione. Lo fa limitando l'accesso ai modelli agli oggetti che il codice dell'applicazione rende specificamente disponibili. Ciò significa che i progettisti possono concentrarsi esclusivamente sulla presentazione dei dati (la vista) e il programmatore dell'applicazione può concentrarsi sul controllo dell'applicazione (il controller) e sulla logica di business e sulla gestione dei dati (il modello) in Model-View-Controller (MVC) sviluppo. MVC è un modello di sviluppo ben accettato che semplifica sia lo sviluppo che la manutenzione continua di applicazioni sofisticate.

Dove lo uso?

La velocità viene utilizzata con successo in:

  • Applicazioni Web basate su servlet
  • Generazione di codice Java e SQL
  • Elaborazione e trasformazione XML
  • Elaborazione del testo, come la generazione di file RTF

La velocità è più comunemente utilizzata come motore di rendering per lo sviluppo di applicazioni Web basate su servlet Java, in sostituzione o in combinazione con JSP e altre tecnologie di rendering. Oltre alla sintassi del modello semplice e gestibile, Velocity viene utilizzato nello sviluppo Web perché il suo linguaggio modello può manipolare e presentare i dati, non creare dati. Ciò scoraggia la programmazione all'interno dei modelli. Questa è una buona cosa; mantiene la logica aziendale e dell'applicazione del codice Java al posto a cui appartengono.

Velocity è adatto allo sviluppo Web J2EE (Java 2 Platform, Enterprise Edition) perché la piattaforma supporta tecnologie di output diverse da JSP. Sebbene JSP sia incluso nella specifica J2EE, J2EE non richiede il suo utilizzo.

Come funziona?

Si utilizza lo stesso processo generale per creare un'applicazione basata sulla velocità come si farebbe con qualsiasi applicazione. Consideriamo un esempio più interessante rispetto all'applicazione Hello World sopra. Supponiamo che gestisci un negozio di animali e desideri generare un'e-mail per annunciare una vendita. Innanzitutto, è necessario progettare l'email e quindi sviluppare il modello e il codice in base a quel design.

Considerazioni in fase di progettazione

Devi considerare tre elementi per il tuo design:

  • Quali dati includere nell'email
  • Ciò che formano gli elementi di dati devono assumere (ad esempio, come List, Mapo String)
  • Come chiamare questi elementi di dati

Per questo esempio, supponiamo che tu decida di vendere tre animali domestici, ciascuno con un prezzo pubblicizzato diverso. Decidi di utilizzare una mappa per associare ogni nome di animale domestico e il suo prezzo, quindi memorizzare tutte e tre le mappe in un elenco. Chiami questa lista petList, il nome dell'animale domestico namee il prezzo come pricenella mappa. Ora che hai identificato i dati rilevanti, la loro rappresentazione e i criteri di denominazione, puoi scrivere il codice e il design del modello.

Scrivi il codice e il design del modello

Dopo aver concordato le specifiche dei dati, Velocity ti consente di scrivere il codice e progettare il modello in parallelo. Il designer integra i dati nel contenuto della presentazione non di dati (come immagini, testo e così via) nel modello. In questo caso, scriviamo semplicemente nel corpo dell'email:

$ petList.size () Animali in vendita! Siamo orgogliosi di offrire questi ottimi animali domestici a questi prezzi incredibili. Solo questo mese, scegli tra: #foreach ($ pet in $ petList) $ pet.name solo per $ pet.price #end Chiama oggi!

In qualità di programmatore, devi:

  • Recupera tutti i dati dalle origini dati: un database tramite JDBC (Java Database Connectivity), un file o semplicemente qualcosa di calcolato
  • Metti quei dati nel contesto usando i nomi concordati
  • Renderizza il modello con il contesto per produrre l'output

Potresti ricordare dall'esempio Hello World che ho fatto riferimento alla classe VelocityContextcome al contesto . Modellato dopo a java.util.Map, il contesto è un oggetto che contiene i dati forniti dall'applicazione o dal servlet a cui accede il modello.

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') 

Ciò produrrebbe lo stesso output e rappresenterebbe meglio ciò che sta realmente accadendo. Tuttavia, l'altro modo in cui utilizza la notazione delle proprietà è più facile da leggere e non collega il modello all'implementazione specifica della classe di dati. Ad esempio, puoi sostituire il Mapin Listcon una classe che ha metodi pubblici getName()e getPrice(), e il modello di esempio originale contenente quanto segue continuerà a funzionare:

 $ pet.name solo per $ pet.price