Pokrenite Velocity Template Engine

Velocity Template Engine omogućuje vam prikaz podataka iz aplikacija i servleta. Primarno korišten za razvoj dinamičnih web stranica temeljenih na servletima, Velocityovo čisto razdvajanje predloška i Java koda čini ga idealnim za MVC web razvoj. Kao općeniti mehanizam predloška, ​​Velocity odgovara mnogim drugim svrhama, poput generiranja koda, generiranja i transformacije XML-a i obrade tekstualnog toka. Ovaj članak uvodi Velocity Template Language (VTL) i pruža primjere kako koristiti Velocity engine, uključujući kako generirati web sadržaj u Java servlet okruženju.

Velocity je alat za predloške otvorenog koda koji je razvila međunarodna volonterska zajednica, a čiji je domaćin projekt Jakarta iz Zaklade Apache Software. Na web mjestu projekta Jakarta Velocity Project, s kojeg možete preuzeti besplatno dostupni izvorni kod, uspješna i rastuća zajednica korisnika spremna je odgovoriti na pitanja i ponuditi rješenja za uobičajene probleme s predlošcima. Velocity je nadahnut pionirskim projektom WebMacro, radom na kojem smo zahvalni u zajednici Velocity.

U ovom članku predstavljam kratki priručnik o Velocity Template Engineu i njegovom jeziku predloška, ​​Velocity Template Language (VTL). Također sam pokazao kako koristiti Velocity kroz nekoliko primjera.

Pozdrav svijetu, naravno

Nijedno objašnjenje predmeta koji se odnosi na programiranje ne bi bilo cjelovito bez primjera Hello World. Svaka aplikacija koja koristi Velocity zahtijeva dva dijela. Prvi je predložak, koji je u ovom primjeru datoteka koja se naziva helloworld.vm:

Pozdrav $ name! Dobrodošli u Velocity!

Drugi je odgovarajući Java program nazvan HelloWorld.java:

import java.io.StringWriter; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; javna klasa HelloWorld {public static void main (String [] args) prvo baca iznimku {/ *, dobiva i inicijalizira motor * / VelocityEngine ve = new VelocityEngine (); ve.init (); / * dalje, uzmite predložak * / Template t = ve.getTemplate ("helloworld.vm"); / * stvoriti kontekst i dodati podatke * / VelocityContext context = new VelocityContext (); context.put ("ime", "Svijet"); / * sada generira predložak u StringWriter * / StringWriter Writer = new StringWriter (); t.merge (kontekst, pisac); / * prikaži svijet * / System.out.println (writer.toString ()); }}

Sada, kad kompajlirate i pokrenete ovaj program, vidjet ćete izlaz:

Pozdrav svijete! Dobrodošli u Velocity!

Ovo je trivijalan primjer, ali sadrži ključne dijelove koji vam daju ideju o čemu se radi u predlošku brzine.

Zašto bih ga trebao koristiti?

Dizajniran kao jednostavan alat za opće predloške, Velocity je koristan u bilo kojem području Java aplikacije koje zahtijeva formatiranje i prezentaciju podataka. Velocity biste trebali koristiti iz sljedećih razloga:

  • Prilagođava se mnogim područjima primjene
  • Nudi jednostavnu, jasnu sintaksu za dizajner predloška
  • Nudi jednostavan model programiranja za programere
  • Budući da su predlošci i kod zasebni, možete ih samostalno razvijati i održavati
  • Velocity engine lako se integrira u bilo koje Java aplikacijsko okruženje, posebno u servlete
  • Brzina omogućuje predlošcima pristup bilo kojoj javnoj metodi podatkovnih objekata u kontekstu

Posljednja je stvar važna - znači da možete ponovno upotrijebiti postojeće predmete. Dakle, objekti koje želite koristiti u predlošcima ne trebaju biti strukturirani na određeni način, poput JavaBeans-a, ili implementirati posebne I / O ili načine životnog ciklusa, poput JSP (JavaServer Pages) tagliba. Jedini uvjet je da su metode javne. O tome ćete više vidjeti kad detaljno obradimo jezik predloška.

Jedna od snaga Velocityja je u tome što snažno provodi razdvajanje funkcionalne odgovornosti unutar aplikacije. To čini ograničavajući pristup predlošku objektima koje kod aplikacije posebno čini dostupnim. To znači da se dizajneri mogu usredotočiti isključivo na prezentaciju podataka (pogled), a programer aplikacija na kontrolu aplikacija (kontroler) i poslovnu logiku i upravljanje podacima (model) u Model-View-Controller (MVC) razvoj. MVC je dobro prihvaćen obrazac razvoja koji pojednostavljuje razvoj i trajno održavanje sofisticiranih aplikacija.

Gdje da ga koristim?

Brzina se uspješno koristi u:

  • Web aplikacije temeljene na servletima
  • Generiranje Java i SQL koda
  • XML obrada i transformacija
  • Obrada teksta, poput stvaranja RTF datoteka

Brzina se najčešće koristi kao mehanizam za prikazivanje za razvoj web aplikacija temeljenih na Java servletima, umjesto ili zajedno s JSP-ovima i drugim tehnologijama prikazivanja. Uz jednostavnu, održivu sintaksu predloška, ​​Velocity se koristi u web razvoju jer njegov jezik predložaka može manipulirati i prezentirati podatke, a ne stvarati podatke. To obeshrabruje programiranje u predlošcima. Ovo je dobra stvar; zadržava poslovnu i aplikacijsku logiku vašeg Java koda tamo gdje im je mjesto.

Brzina je vrlo pogodna za web razvoj J2EE (Java 2 Platform, Enterprise Edition) jer platforma podržava izlazne tehnologije koje nisu JSP. Iako je JSP uključen u specifikaciju J2EE, J2EE ne zahtijeva njegovu upotrebu.

Kako radi?

Koristite isti opći postupak za stvaranje aplikacije temeljene na brzini kao i bilo koju drugu aplikaciju. Razmotrimo zanimljiviji primjer od gore navedene aplikacije Hello World. Pretpostavimo da imate trgovinu kućnih ljubimaca i želite generirati e-poruku kojom ćete najaviti prodaju. Prvo morate dizajnirati e-poštu, a zatim razviti predložak i kôd na temelju tog dizajna.

Razmatranja vremena dizajna

Za svoj dizajn morate uzeti u obzir tri elementa:

  • Koje podatke uključiti u e-poštu
  • Što čine elemente podataka treba uzeti (na primjer, kao List, Mapili String)
  • Kako nazvati te elemente podataka

For this example, let's suppose you decide on three pets for sale, each with a different advertised price. You decide to use a map to associate each pet name and its price, and then store all three maps in a list. You call this list petList, the pet name name, and the price as price in the map. Now that you have identified the relevant data, its representation, and naming criteria, you can write the code and the template's design.

Write the code and template design

Once you agree on data specifics, Velocity lets you write the code and design the template in parallel. The designer integrates the data into the nondata presentation content (like images, text, and so on) in the template. In this case, we simply write in the email body:

 $petList.size() Pets on Sale! We are proud to offer these fine pets at these amazing prices. This month only, choose from: #foreach( $pet in $petList ) $pet.name for only $pet.price #end Call Today! 

As the programmer, you must:

  • Retrieve all data from the data sources -- a database via JDBC (Java Database Connectivity), a file, or just something calculated
  • Put that data into the context using the agreed-upon names
  • Render the template with the context to produce output

You may recall from the Hello World example that I referred to class VelocityContext as the context. Modeled after a java.util.Map, the context is an object that holds data provided by the application or servlet that the template accesses.

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

To bi proizvelo isti rezultat i bolje predstavlja ono što se zapravo događa. Međutim, drugi način koji koristi notaciju svojstava je lakši za čitanje i ne veže vaš predložak za specifičnu implementaciju klase podataka. Na primjer, možete zamijeniti Mapin Lists razredom koji ima javne metode getName()i getPrice(), a izvorni primjer predloška koji sadrži sljedeće nastavit će raditi:

 $ pet.name za samo $ pet.price