Mulakan Velocity Template Engine

Velocity Template Engine membolehkan anda membuat data dari dalam aplikasi dan servlet. Terutama digunakan untuk mengembangkan Laman Web yang dinamis, servlet, pemisahan templat Velocity dan kod Java menjadikannya ideal untuk pengembangan Web MVC. Sebagai mesin templat umum, Velocity sesuai dengan banyak tujuan lain, seperti penjanaan kod, penjanaan dan transformasi XML, dan pemprosesan aliran teks. Artikel ini memperkenalkan Velocity Template Language (VTL) dan memberikan contoh bagaimana menggunakan mesin Velocity, termasuk cara menghasilkan kandungan Web dalam lingkungan servlet Java.

Velocity adalah alat templat sumber terbuka yang dikembangkan oleh komuniti sukarelawan antarabangsa dan dihoskan oleh Projek Jakarta Foundation Foundation Apache. Di Laman Web Projek Velocity Jakarta, di mana anda boleh memuat turun kod sumber yang tersedia secara bebas, komuniti pengguna yang berkembang dan berkembang bersedia untuk menjawab soalan dan menawarkan penyelesaian untuk masalah templat umum. Velocity diilhamkan oleh projek WebMacro perintis, sebuah karya yang kami syukuri dalam komuniti Velocity.

Dalam artikel ini, saya membentangkan buku asas pendek pada Velocity Template Engine dan bahasa templatnya, Velocity Template Language (VTL). Saya juga menunjukkan cara menggunakan Velocity melalui beberapa contoh.

Hello World, tentu saja

Tiada penjelasan mengenai subjek yang berkaitan dengan pengaturcaraan akan lengkap tanpa contoh Hello World. Sebarang aplikasi yang menggunakan Velocity memerlukan dua bahagian. Yang pertama adalah templat, yang dalam contoh ini adalah fail yang disebut helloworld.vm:

Helo $ nama! Selamat Datang di Velocity!

Yang kedua adalah program Java yang disebut HelloWorld.java:

import java.io.StringWriter; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; kelas awam HelloWorld {public static void main (String [] args) membuang Pengecualian {/ * pertama, dapatkan dan inisialisasi enjin * / VelocityEngine ve = VelocityEngine baru (); ve.init (); / * seterusnya, dapatkan Templat * / Templat t = ve.getTemplate ("helloworld.vm"); / * buat konteks dan tambahkan data * / Konteks VelocityContext = VelocityContext baru (); konteks.put ("nama", "Dunia"); / * sekarang menjadikan templat menjadi StringWriter * / StringWriter penulis = StringWriter baru (); t.merge (konteks, penulis); / * tunjukkan Dunia * / System.out.println (writer.toString ()); }}

Sekarang, apabila anda menyusun dan menjalankan program ini, anda akan melihat outputnya:

Hai dunia! Selamat Datang di Velocity!

Ini adalah contoh remeh, tetapi ia mengandungi bahagian-bahagian penting untuk memberi anda gambaran tentang templat Velocity.

Mengapa saya mesti menggunakannya?

Dirancang sebagai alat templat umum yang mudah digunakan, Velocity berguna di mana-mana kawasan aplikasi Java yang memerlukan pemformatan dan penyajian data. Anda harus menggunakan Velocity kerana alasan berikut:

  • Ia menyesuaikan diri dengan banyak bidang aplikasi
  • Ia menawarkan sintaks yang ringkas dan jelas untuk pereka templat
  • Ia menawarkan model pengaturcaraan yang sederhana untuk pemaju
  • Kerana templat dan kodnya terpisah, anda boleh mengembangkan dan mengekalkannya secara bebas
  • Mesin Velocity dengan mudah disatukan ke dalam lingkungan aplikasi Java, terutama servlet
  • Velocity membolehkan templat mengakses kaedah umum objek data dalam konteks

Perkara terakhir adalah penting - ini bermaksud bahawa anda boleh menggunakan semula kelas yang ada. Jadi, objek yang ingin anda gunakan dalam templat anda tidak perlu disusun dengan cara tertentu, seperti JavaBeans, atau menerapkan mode I / O atau siklus hidup khas, seperti taglib JSP (JavaServer Pages). Satu-satunya syarat adalah kaedah untuk umum. Anda akan melihat lebih banyak perkara ini apabila kita merangkumi bahasa templat secara terperinci.

Salah satu kelebihan Velocity adalah bahawa ia sangat menegakkan pemisahan tanggungjawab fungsi dalam aplikasi. Ia melakukannya dengan menghadkan akses templat ke objek yang disediakan oleh kod aplikasi. Ini bermaksud bahawa pereka dapat memfokuskan secara eksklusif pada penyajian data (tampilan), dan pengaturcara aplikasi dapat memusatkan perhatian pada kontrol aplikasi (pengawal) dan logik perniagaan dan pengurusan data (model) dalam Model-View-Controller (MVC) pembangunan. MVC adalah corak pembangunan yang dapat diterima dengan baik yang menyederhanakan pembangunan dan penyelenggaraan berterusan aplikasi canggih.

Di mana saya menggunakannya?

Velocity berjaya digunakan dalam:

  • Aplikasi Web berasaskan servlet
  • Penjanaan kod Java dan SQL
  • Pemprosesan dan transformasi XML
  • Pemprosesan teks, seperti penghasilan fail RTF

Velocity paling sering digunakan sebagai mesin rendering untuk pengembangan aplikasi Web berbasis servlet Java, sebagai pengganti atau bersama dengan JSP dan teknologi rendering lain. Selain sintaks templat yang mudah dikendalikan, Velocity digunakan dalam pengembangan Web kerana bahasa templatnya dapat memanipulasi dan menampilkan data, bukan membuat data. Ini tidak menggalakkan pengaturcaraan dalam templat. Ini adalah perkara yang baik; ini menyimpan logik perniagaan dan aplikasi kod Java anda di tempat mereka berada.

Velocity sangat cocok untuk pengembangan Web J2EE (Java 2 Platform, Enterprise Edition) kerana platform ini menampung teknologi output selain JSP. Walaupun JSP termasuk dalam spesifikasi J2EE, J2EE tidak memerlukan penggunaannya.

Bagaimanakah ia berfungsi?

You use the same general process to create a Velocity-based application as you would any application. Let's consider a more interesting example than the Hello World application above. Suppose you operate a pet store and wish to generate an email blast to announce a sale. First, you must design the email and then develop the template and code based on that design.

Design-time considerations

You need to consider three elements for your design:

  • Which data to include in the email
  • What form the data elements should take (for example, as List, Map, or String)
  • What to call those data elements

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

Ini akan menghasilkan output yang sama, dan lebih baik menggambarkan apa yang sebenarnya berlaku. Namun, cara lain yang menggunakan notasi harta tanah lebih mudah dibaca dan tidak mengaitkan templat anda dengan pelaksanaan khusus kelas data. Sebagai contoh, anda boleh mengganti Mapdi Listdengan kelas yang mempunyai kaedah awam getName()dan getPrice(), dan templat contoh asal yang mengandungi berikut akan terus berfungsi:

 $ pet.name hanya dengan harga $ pet.price