Die Schablone
... [ Was ist Velocity? ] ... [ Die Schablone ] ... [ Die Java-Klasse ] ... [ Inhaltsverzeichnis ] ...
Übersicht: Die Schablone
Die Schablone beinhaltet die View aus dem MVC-Modell. Sie soll die Daten in einer bestimmten Form aufbereiten und diese darstellen. Ein Velocity-Servlet würde z.B. in der Schablone ein HTML-Dokument hinterlegen, welches Daten in einem Browser darstellen kann. Das Dokument benötigt natürlich Markierungen, die anzeigen, dass an bestimmten Stellen Daten eingefügt werden sollen. Dieses geschieht in Velocity mit der Velocity Template Language (VTL). Die VTL ist sehr einfach zu erlernen, so dass selbst Personen mit geringer oder keiner Programmierkenntnis diese benutzen können. Dieses ist ein großer Vorteil, da die Gestaltung von Daten nicht zwingend von Programmierern getätigt werden braucht. Vor der Entwicklung sind lediglich die Schnittstellen zu definieren, während die Entwicklung von View und Controller vollständig parallel vollzogen werden kann.
Einleitung
Die VTL ist die Schnittstelle zwischen der Schablone und der Java-Klasse. Sie kann Bereiche in der Schablone markieren, so dass an diesen Stellen später Inhalte eingefügt werden.
Die VTL besteht aus Referenzen (Verweisen) und Direktiven (Anweisungen). Referenzen starten immer mit einem "$" während Direktiven mit einem "#" beginnen.
Referenzen
Es gibt drei Typen von Referenzen: Variablen, Eigenschaften und Methoden. Jede Referenz verweißt auf ein beliebiges Objekt. Wird in einer Referenz auf ein anderes Objekt als das "String"-Objekt verwiesen, wird automatisch die "toString"-Methode des Objektes aufgerufen, da die VTL nur Text darstellen kann.
Variablen:
starten immer mit einem"$" gefolgt von einem Buchstaben (a..z, A..Z)
alle folgenden Zeichen dürfen Buchstaben, Ziffern, Unterstrich oder Bindestrich sein
können mit der Anweisung "#set" (siehe unten) innerhalb der Schablone ( #set ($Variable="Wert") ) oder in der Java-Klasse gesetzt werden
Eigenschaften:
werden einer Variable zugeordnet
Notation: $Variable.Eigenschaft
kann zwei Bedeutungen haben:
- gebe den Wert zurück, der im Hashtable "Variable" unter dem Schlüssel "Eigenschaft" zu finden ist
- Kurzform des Methodenaufrufs "$Variable.getEigenschaft()"
Velocity überprüft zur Laufzeit, welche der beiden Möglichkeiten sinnvoll ist und führt diese aus.
Methoden:
ähneln der Notation von Eigenschaften ( "$Variable.Methode()" )
können Parameter übergeben bekommen
ruft die "Methode" der "Variable" auf
Formale Referenzen-Notation
Die oben beschriebene Notation ist die kurze Notation, die auch meistens in der Schablone benutzt wird. Das folgende Beispiel beschreibt aber eine Problematik, die mit dieser Notation in einigen Fällen auftreten könnte:
Die Variable "$studienrichtung" beinhaltet einen der folgenden Werte: "Wirtschafts" oder "Medien". In einer Schablone soll der Satz "Er studiert "Wirtschafts/Medien"informatik" angezeigt werden. Da es sich dabei um ein zusammenhängendes Wort handelt, darf kein Leerzeichen zwischen der Variable und dem Rest des Satzes stehen. In der Schablone würde der Satz so aussehen: "Er studiert $studienrichtunginformatik" Velocity kennt den so angegebenen Variablennamen aber nicht. Die formale Notation für Referenzen bereinigt dieses Problem. Sie besagt, dass alles hinter dem "$"-Zeichen in "{ }" zu stehen hat:
${studienrichtung}
${Variable.Eigenschaft}
${Variable.Methode()}
Direktiven
#set
Die Anweisung "#set" ordnet einer Variable oder einer Eigenschaft "$a" einen Wert "Wert" zu.
Auf der linken Seite des "="-Zeichens steht immer ein Variablenname oder eine Eigenschaft. Die rechte Seite enthält eine der folgenden sieben Möglichkeiten:
Inhalt einer Variable | #set( $value = $value2) |
Wert einer Eigenschaft | #set( $value = $value3.value) |
Ergebnis eines Methodenaufrufs | #set( $value = $value4.getValue()) |
ein String (in "") | #set( $value = "Wert") |
eine Zahl | #set( $value = 123) |
eine Aufzählung | #set( $value = ["Wert1", "Wert2"]) |
ein einfacher arithmetischer Ausdruck | #set( $value = $value2 + 1) |
Wenn der Ausdruck, der zugewiesen werden soll, nicht ermittelt werden kann bzw. sein Ergebnis "null" ist, weist Velocity der Variable bzw. Eigenschaft nichts zu.
#if
Die if-Bedingung beginnt mit "#if" gefolgt von einer Bedingung, die in "( )" steht. "#end" markiert das Ende der Bedingung.
#if ( $value )
Alles klar!
#end |
Die im Beispiel stehende Bedingung in den runden Klammern kann zwei Bedeutungen haben:
- der Typ von $value ist boolean (true => Ausgabe des Textes; sonst keine Ausgabe)
- der Typ von $value ist nicht boolean (Ausgabe des Textes, wenn der Wert von $value ungleich "null" ist)
Vor dem "#end" kann mittels eines "#elseif" eine weitere Bedingung gestellt werden, die geprüft wird, wenn die erste Bedingung (hinter "#if") zu "false" ausgewertet wurde. Einem "#elseif" können weitere "#elseif"s folgen. Wenn der "else"-Teil an keine weitere Bedingung geknüpft sein soll, kann auch ein einfaches "#else" benutzt werden.
#if( $value < 10 )
kleiner als 10
#elseif( $value == 10 )
gleich 10
#elseif( $value == 16 )
gleich 16
#else
was anderes
#end |
Wie das Beispiel zeigt, können Bedingungen auch Vergleiche beinhalten. Auch logische Operatoren sind möglich. Die Notation ist dabei dieselbe wie in Java.
#if( ($value < 10 && $value > 5) || ($value == 42) ) |
#foreach
Die "#foreach"-Schleife ist eine besonders wichtige Anweisung in der VTL. Häufig wird der Ersteller der Schablone nicht wissen, wie viele Elemente sich in einer Liste o.ä. befinden, die ausgegeben werden soll. In diesem Fall wird die "#foreach"-Schleife verwendet. Sie durchläuft automatisch eine Liste und gibt in jedem Durchlauf einen Wert an eine Variable zurück.
#foreach( $product in $allProducts )
$product
#end |
Das Beispiel zeigt eine Schablone, in der eine Liste von Produkten ausgegeben werden soll. Die verschiedenen Produkte sind in der Variable "$allProducts" gespeichert. Mit jedem Schleifendurchlauf wird ein Eintrag aus "$allProducts" herausgelesen und in der Variable "$product" gespeichert.
Als Listentyp erlaubt Velocity drei verschiedene Arten:
1. eine Referenz auf eine Liste (z.B. Hashtable, Vector, Object-Array …)
#foreach( $product in $allProducts )
2. eine Array-Liste
#foreach( $product in ["Produkt1","Produkt2","Produkt3"] )
3. einen Range-Operator
#foreach( $product in [1..3] )
Das Durchlaufen einer Liste erfolgt bei Velocity, indem intern ein Schleifen-Index inkrementiert wird. Über die Variable "$velocityCount" kann auf den momentanen Wert dieses Indizes zugegriffen werden.
#foreach( $product in $allProducts )
Produktnummer = $velocityCount Produktname = $product
#end |
Der Variablenname ("$velocityCount") und der Startwert der Schleife (Standard=1) sind in der Velocity-Eigenschaften-Datei "velocity.properties" festgelegt.
# Default name of the loop counter
# variable reference
directive.foreach.counter.name = velocityCount
# Default starting value of the loop
# counter variable reference
directive.foreach.counter.initial.value = 1 |
Die Einstellungen in dieser Datei beziehen sich auf alle Schleifen innerhalb der Schablone.
#include
Die Anweisung "#include" erlaubt es, an einer Stelle in der Schablone eine weitere Datei einzufügen. Velocity ersetzt hierfür einfach die Anweisung durch den Inhalt der angegebenen Datei(en). Aus Sicherheitsgründen können nur Dateien angegeben werden, die sich im Verzeichnis der Schablone befinden.
#include( "one.txt" )
#include( "one.txt","two.txt","three.htm" ) |
Auch Variablen, die einen Dateinamen beinhalten, können angegeben werden:
#include( "one.txt", $filename ) |
#parse
Die "#parse"-Anweisung funktioniert genauso wie die "#include"-Anweisung. Der Unterschied ist, dass bei "#parse" die VTL-Teile in der angegebenen Datei vonVelocity bearbeitet werden. Ein weiterer Unterschied ist, dass "#parse" nur einen Dateinamen übergeben werden kann.
Eine Datei, die mittels "#parse" eingebunden wird kann wiederum "#parse"-Anweisungen enthalten. Dadurch kann Rekursion erzeugt werden (siehe Beispiel unten). Damit es zu keiner Endlosrekursion kommt, ist in der Datei "velocity.properties" ein Wert angegeben, der die maximale Anzahl von Rekursionsstufen festlegt (Standard=10)
directive.parse.max.depth = 10 |
Beispiel für eine Rekursion mit "#parse":
Datei countDown.vm:
01 Count down.
02 #set( $count = 8 )
03 #parse( "rekursion.vm" )
04 All done with dofoo.vm!
|
Datei rekursion.vm
01 $count
02 #set( $count = $count - 1 )
03 #if( $count > 0 )
04 #parse( "rekursion.vm" )
05 #else
06 Alles klar!
07 #end
|
die Ausgabe:
Count down
8
7
6
5
4
3
2
1
Alles klar.
|
#stop
"#stop" beendet die Ausführung einer Schablone. Dieses kann sehr hilfreich beim Finden von Fehlern sein.
#macro
Häufig wiederkehrende Abschnitte in einer Schablone können in einem Velocimacro (Makro) definiert und dann beliebig oft ausgeführt werden.
#macro( beispiel )
--------T-R-E-N-N-L-I-N-I-E--------
#end |
Der Aufruf des Makros erfolgt im Beispiel über "#beispiel()". Velocity ersetzt jedes "#beispiel()" durch den definierten Teil des Makros.
Ein Makroaufruf kann beliebig viele Argumente (getrennt durch Leerzeichen) enthalten, solange diese in der Makrodefinition definiert sind. Folgende Typen sind als Argument erlaubt:
Referenz: alles was mit "$" startet
String : "Text"
Zahl : 1, 2 etc
IntegerRange : [ 1..2] oder [$value1 .. $value2]
ObjectArray : [ "a", "b", "c"]
boolscher Wert (true oder false)
01 #macro( tablerows $somelist )
02 #foreach( $something in $somelist )
03 $something
04 #end
05 #end
06
07 #set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
08
09 #tablerows( $greatlakes )
|
Das Beispiel ist ein Teil einer Schablone. Nachdem Velocity die Schablone bearbeitet hat, wird folgendes dargestellt:
Superior
Michigan
Huron
Erie
Ontario
|
Wie man erkennt, wird die Ausgabe der Listeneinträge vom Makro übernommen, welches eine Liste an Einträgen übergeben bekommt.
Das Beispiel zeigt, dass Makros immer vor dem ersten Aufruf definiert werden müssen, damit Velocity diese erkennt.
Dem Beispiel kann man außerdem entnehmen, dass Makros "inline" in einer Schablone definiert werden können. Der Nachteil daran ist, dass man von verschiedenen Schablonen aus nicht auf dieses Makro zugreifen kann. Mehr Sinn macht da das Ablegen der Makros in Bibliotheken, auf die von jeder Schablone aus zugegriffen werden kann. Diese Bibliotheken werden in der Datei "velocity.properties" definiert:
velocimacro.library = VM_global_library.vm
Velocity erlaubt es, mehrere Dateinamen (getrennt mit Kommata) hintereinander anzugeben.
Weiterhin wird in dieser Datei definiert, ob "inline"-Makros erlaubt sind (velocimacro.permissions.allow.inline = true
) und ob Makros aus Bibliotheken in Schablonen überschrieben werden können (velocimacro.permissions.allow.inline.to.replace.global = false
).
Weitere Optionen sind:
velocimacro.permissions.allow.inline.local.scope
Werte sind true/false (Standard)
Wird der Wert auf "true" gesetzt, kann nur aus der aktuellen Schablone auf dieses Makro zugegriffen werden. Für andere Schablonen ist dieses Makro unsichtbar.
velocimacro.context.localscope
Werte sind true/false (Standard)
Wird der Wert auf "true" gesetzt, sind alle Variablenänderungen (gesetzt mit #set) nur lokal auf das Makro begrenzt.
velocimacro.library.autoreload
Werte sind true/false (Standard)
Wird der Wert auf "true" gesetzt, prüft Velocity vor dem Aufruf eines Makros in einer Bibliothek, ob sich das Makro verändert hat und lädt dieses notfalls erneut.
Diese Option ist nur für die Entwicklung vorgesehen, damit bei einer Änderung einer Bibliothek nicht das gesamte Servlet neu gestartet werden muss.
Kommentare
Die VTL unterstützt auch Kommentare. Ein Zeilenkommentar wird mit "##" eingeleitet. Mehrzeilige Kommentare starten mit "#*" und enden mit "*#".
Sonderzeichen
Wenn definierte Variablen ausgegeben werden sollen (NICHT deren Wert) benötigt Velocity einen Hinweis, dass der Name und nicht der Wert gemeint ist.
Dieses geschieht durch das "\"-Zeichen:
( #set ($name= "Hans")
$name
\$name
\\$name |
Ausgabe:
Das Beispiel zeigt, dass "\\" von Velocity zu "\" ausgewertet wird ("\" ist "linksgebunden").
... [ Was ist Velocity? ] ... [ Die Schablone ] ... [ Die Java-Klasse ] ... [ Inhaltsverzeichnis ] ...