Velocityテンプレートエンジンを起動します

Velocity Template Engineを使用すると、アプリケーションおよびサーブレット内からデータをレンダリングできます。主に動的なサーブレットベースのWebサイトの開発に使用され、VelocityはテンプレートとJavaコードを明確に分離しているため、MVCWeb開発に最適です。一般的なテンプレートエンジンとして、Velocityは、コード生成、XMLの生成と変換、テキストストリーム処理など、他の多くの目的に適しています。この記事では、Velocityテンプレート言語(VTL)を紹介し、Javaサーブレット環境でWebコンテンツを生成する方法など、Velocityエンジンの使用方法の例を示します。

Velocityは、国際的なボランティアコミュニティによって開発され、Apache SoftwareFoundationのJakartaProjectによってホストされているオープンソースのテンプレートツールです。無料で入手できるソースコードをダウンロードできるJakartaVelocity Project Webサイトでは、活発で成長しているユーザーコミュニティが質問に答え、一般的なテンプレートの問題の解決策を提供する準備ができています。Velocityは、先駆的なWebMacroプロジェクトに触発されました。これは、Velocityコミュニティの私たちが感謝している作業です。

この記事では、Velocityテンプレートエンジンとそのテンプレート言語であるVelocityテンプレート言語(VTL)についての簡単な入門書を紹介します。また、いくつかの例を通じてVelocityの使用方法を示します。

もちろん、Hello World

Hello Worldの例がなければ、プログラミング関連の主題の説明は完全ではありません。Velocityを使用するアプリケーションには、2つの部分が必要です。1つ目はテンプレートで、この例では次のファイルですhelloworld.vm

こんにちは$ name!Velocityへようこそ!

2つ目は、対応するJavaプログラムHelloWorld.javaです。

インポート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)throws Exception {/ *最初に、エンジンを取得して初期化します* / VelocityEngine ve = new VelocityEngine(); ve.init(); / *次に、テンプレートを取得します* / Template t = ve.getTemplate( "helloworld.vm"); / *コンテキストを作成してデータを追加します* / VelocityContext context = new VelocityContext(); context.put( "name"、 "World"); / *テンプレートをStringWriterにレンダリングします* / StringWriter writer = new StringWriter(); t.merge(コンテキスト、ライター); / *世界を表示します* / System.out.println(writer.toString()); }}

これで、このプログラムをコンパイルして実行すると、次の出力が表示されます。

"こんにちは世界" Velocityへようこそ!

これは些細な例ですが、Velocityテンプレートが何であるかを理解するための重要な部分が含まれています。

なぜ私はそれを使うべきですか?

使いやすい一般的なテンプレートツールとして設計されたVelocityは、データのフォーマットと表示を必要とするJavaアプリケーション領域で役立ちます。次の理由でVelocityを使用する必要があります。

  • それは多くのアプリケーション分野に適応します
  • テンプレートデザイナにシンプルで明確な構文を提供します
  • 開発者向けのシンプルなプログラミングモデルを提供します
  • テンプレートとコードは分離されているため、個別に開発および保守できます
  • Velocityエンジンは、Javaアプリケーション環境、特にサーブレットに簡単に統合できます。
  • Velocityを使用すると、テンプレートはコンテキスト内のデータオブジェクトのパブリックメソッドにアクセスできます

最後のポイントは重要です。つまり、既存のクラスを再利用できるということです。したがって、テンプレートで使用するオブジェクトは、JavaBeansのように特定の方法で構造化する必要はなく、JSP(JavaServer Pages)taglibsのように特別なI / Oまたはライフサイクルモードを実装する必要もありません。唯一の要件は、メソッドがパブリックであることです。テンプレート言語について詳しく説明すると、この詳細がわかります。

Velocityの強みの1つは、アプリケーション内の機能的責任の分離を強力に実施することです。これは、アプリケーションコードが具体的に利用可能にするオブジェクトへのテンプレートアクセスを制限することによって行われます。つまり、設計者はデータの表示(ビュー)に専念でき、アプリケーションプログラマーはModel-View-Controller(MVC)のアプリケーション制御(コントローラー)とビジネスロジックおよびデータ管理(モデル)に専念できます。開発。MVCは、洗練されたアプリケーションの開発と継続的なメンテナンスの両方を簡素化する、広く受け入れられている開発パターンです。

どこで使用しますか?

Velocityは次の場所で正常に使用されます:

  • サーブレットベースのWebアプリケーション
  • JavaおよびSQLコードの生成
  • XMLの処理と変換
  • RTFファイル生成などのテキスト処理

Velocityは、JSPやその他のレンダリング技術の代わりに、またはそれらと組み合わせて、JavaサーブレットベースのWebアプリケーション開発用のレンダリングエンジンとして最も一般的に使用されます。簡単で保守しやすいテンプレート構文に加えて、Velocityは、そのテンプレート言語がデータを作成するのではなく、データを操作および表示できるため、Web開発で使用されます。これにより、テンプレート内でのプログラミングが妨げられます。これは良いことです。Javaコードのビジネスロジックとアプリケーションロジックをそれらが属する場所に保持します。

プラットフォームはJSP以外の出力テクノロジに対応しているため、VelocityはJ2EE(Java 2プラットフォーム、Enterprise Edition)Web開発に最適です。JSPはJ2EE仕様に含まれていますが、J2EEを使用する必要はありません。

それはどのように機能しますか?

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

これは同じ出力を生成し、実際に起こっていることをよりよく表します。ただし、プロパティ表記を使用するもう1つの方法は読みやすく、テンプレートをデータクラスの特定の実装に結び付けません。たとえば、置き換えることができますMapListのパブリックメソッドを持つクラスを持つgetName()getPrice()し、次を含む元の例のテンプレートが作業していきますが。

 $ pet.nameは$ pet.priceのみ