このガイドについて

Velocity ユーザガイドは、ページデザイナやコンテンツ・プロパイダに Velocity と、 Velocity の単純ながらも強力なスクリプト言語である Velocity テンプレート言語 (VTL:Velocity Template Language) の構文を理解していただくことを目的としています。 このガイドで出てくる例の多くは、Web サイトで動的に内容を埋め込むための Velocity の使い方を扱っていますが、VTL の例はすべて、その他のページやテンプレートにも同様に適用できます。

Velocity を選んでいただきありがとうございます。

 
Velocityとは?

Velocity は、Java ベースのテンプレートエンジンです。 Velocityを使うと、Web ページデザイナが Java コードで定義されたメソッドを参照できます。Model-View-Controller(MVC) モデルに基づく Web サイト開発で、 Java プログラマと Web デザイナが並行して作業できます。つまり、 Web ページデザイナは素晴らしいデザインのサイトをつくることだけに集中し、プログラマは最高のコードを書くことだけに集中できるということです。 Velocity は、Java コードを Web ページから切り離し、長い目で見ればより保守しやすい Web サイトを実現し、 Java Server Pages(JSP) や PHP の実現可能な代替案を提供します。

Velocity は Web ページや SQL、PostScript といった出力をテンプレートから生成するのに使えます。ソースコードや帳票を生成する単体のユーティリティとしても使えますし、他のシステムに統合されるコンポーネントとしても使えます。 Velocityは、Turbine Web アプリケーションフレームワークでテンプレートサービスを提供します。 Velocity と Turbine の組み合わせで、真の MVC モデルにしたがって Web アプリケーションを開発できるテンプレートサービスを提供します。

 
Velocity で何ができるの?
Mud Store のサンプル

あなたが陶土を専門に扱うオンラインストアのページデザイナであるとしましょう。オンラインストアの名前は「Online Mud Store」としましょう。商売は繁盛しています。顧客はいろいろな種類や量の商品を発注します。サイトにはユーザー名とパスワードを使用してログインし、注文内容を確認したり、さらに商品を購入したりできます。現在、テラコッタ土 [訳注:素焼き用の陶土] はセール中で、とても人気があります。赤土もセール中ですが、あまり人気が無く、少数の顧客が定期的に買うぐらいで、いつもは Web ページの片隅に追いやられています。各顧客に関する情報 [購買履歴など] はデータベースに記録されます。そんなある日、こんな疑問が湧きます。「特別セールを行う時に、セール対象の商品に最も興味を持っている顧客をターゲットとするのに Velocity を使うのはどうだろう?」

Velocity なら、オンライン訪問者ごとに Web ページを簡単にカスタマイズできます。「The Mud Room」の Web サイトデザイナであるあなたは、顧客がサイトログイン後に見る Web ページを作ろうと思っています。

会社でソフトウェアエンジニアと打ち合わせをした結果、 $customer に現在ログインしている顧客に関する情報を保持し、 $mudsOnSpecial で現在セール中の全ての種類の商品の情報を保持することになりました。$flogger オブジェクトには、宣伝に役立つメソッドが入っています。当面の作業では、これらの3つのリファレンスにだけ注目しましょう。ソフトウェアエンジニアがどのように必要な情報をデータベースから抽出するかについては気にしなくてよく、その情報が使えることだけ知っていればよいということ注目してください。つまり、あなたもソフトウェアエンジニアも、自分の仕事にだけ注力できるということです。

以下の VTL 文を Web ページに埋め込みます。

<HTML>
<BODY>
Hello $customer.Name!
<table>
#foreach( $mud in $mudsOnSpecial )
#if ( $customer.hasPurchased($mud) )
<tr>
<td>
$flogger.getPromo( $mud )
</td>
</tr>
#end
#end
</table>
</BODY>

foreach 文の詳細は後段で説明しますが、ここで重要なのは、この短いスクリプトがあなたの Web サイトにあたえるインパクトです。赤土を好む顧客がログインしたとき、赤土がセール中であれば、この顧客向けに、赤土がセール中であることを特に目につくように表示します。テラコッタ土購入歴の長い顧客がログインしたときには、テラコッタ土のセールのお知らせを一番目立つ場所に表示します。 Velocityの柔軟性は極めて高く、あとはあなたの創造力次第です。

VTLリファレンスでは、その他にもたくさんの Velocity 要素が記述されており、これらを組み合わせることで、 Web サイトの存在感 を高めるのに必要なパワーと柔軟性が得られます。これらの要素に詳しくなれば、Velocity のパワーをさらに発揮できるでしょう。

 
 
Velocity テンブレート言語 (VTL): はじめに

Velocity テンプレート言語(VTL:Velocity Template Language) は、 Web ページに動的な内容を取り込むのに最も簡単、単純で、無駄のない方法となることを目標としています。ほとんどプログラミング経験のない Web ページ開発者でも、 VTL を使えばすぐに、動的な内容を Web サイトに取り込めるようになるはずです。

VTL では Web サイトにおいて動的な内容を埋め込むのにリファレンス を使いますが、変数はその一種です。変数とは Java コードで定義したものを参照するリファレンスの一種で、 Web ページ内の VTL から変数の値を取得できます。 HTML 文書に埋め込むことができる VTL 文の例を次に示します:

#set( $a = "Velocity" )

全ての VTL 文がそうであるように、この VTL 文は 「#」から始まって、set という指示子を含みます。 Webページが要求されたとき、Velocity テンプレートエンジンは Web ページを走査して全ての 「#」を見つけ、それぞれについて、どれが VTL 文の始まりでどれが VTL と無関係かを判定します。

#」の後に指示子(set)が続いています。 set 指示子は、(括弧で囲まれた)式 ─ 変数 を割り当てる等式 ─ を使います。変数は左側で値は右側になります。この2つは、「=」で区切られます。

上の例では、変数は $a で値は Velocity です。全てのリファレンスがそうであるように、この変数は 「$」で始まります。値は常に引用符で囲まれます。Velocity では、文字列 (テキストに基づく情報) だけが変数に渡されるので、データ型に対する混乱は発生しません。

以下の簡単なルールが、Velocity がどのように動作するかをさらに理解するのに役立つでしょう。 リファレンスは、「$」 から始まって、何かを取得するのに使います。指示子は、「#」 から始まって、何かを行うのに使います。

上の例では、#set は、値を変数に割り当てるのに使われます。変数 ($a) は、「Velocity」を出力するのにテンプレートで使うことができます。

 
Hello Velocity World!

一旦変数に値が割り当てられたら、HTML 文書のどこででも変数を参照できます。下記の例では、値は $foo に割り当てられて後で参照されます。

<html>
<body>
#set( $foo = "Velocity" )
Hello $foo World!
</body>
<html>

結果として Web ページは、"Hello Velocity World!"を表示します。

VTL 指示子を含んだ文をより読みやすくするために、個々の VTL 文は、新しい行から始めることを推奨しますが、必須ではありません。 set 指示子については、後ほど更に詳しく説明します。

 
コメント

コメントを使うと説明用のテキストを埋め込むことができます。コメントはテンプレートエンジンの出力に含まれません。コメントは、VTL 文が何を行なっているかを他人 (や未来の自分自身) に説明するなど、便利と思われるどんな目的でも使うことができます。下記は、VTL でのコメントの例です。

## 一行コメントです。

一行コメントは、## で始まり行末で終わります。コメントを複数行書こうとする場合、一行コメントをたくさん並べる必要ありません。こういう場合には、複数行コメント (#* で始まり*# で終わります) が利用できます。

この部分は複数行コメントの外なので、
ページには表示されます。
#*
複数行コメントはここからです。ページにはこのテキストは表示されません。
Velocity テンプレートエンジンはこの部分を無視するからです。
*#
ここも複数行コメントの外なので、ページに表示されます。

一行コメントと複数行コメントの動作を分かりやすく説明するいくつかの例を以下に示します。

このテキストは表示されます。 ## このテキストは表示されません。
このテキストは表示されます。
このテキストは表示されます。 #* このテキストは、複数行コメントの一部なので、
表示されません。このテキストも複数行コメントの一部なので、表示されません。
このテキストもまだ表示されません。*# このテキストはコメントの外側なので、
表示されます。
## このテキストは表示されません。

コメントには第3の形式 (VTLコメントブロック) があります。文書の作者やバージョン情報などを格納するために使われるかもしれません。

#**
これは VTL コメントブロックで、
文書の作者やバージョン情報といった
情報を格納するのに使われるかも
しれません。
@author
@version 5
*#
 
リファレンス

VTL には、変数/プロパティ/メソッドという3種類のリファレンスがあります。 VTL を使うデザイナがテンプレートでリファレンスを正しく使えるように、デザイナとエンジニアとの間で、個々のリファレンスの名前について同意しておかなければなりません。

リファレンスに出入りするものはすべて、文字列オブジェクトとみなされます。 $fooという名前のオブジェクト (例えばIntegerオブジェクト) があるならば、 Velocity はオブジェクトを文字列にするために.toString()メソッドを呼びます。

変数
変数の簡略表記は、「$」とそれに続く VTL 識別子 から構成されます。 VTL 識別子は、英字から始めなければなりません (a・・・zまたはA・・・Z)。先頭以外の文字についても、以下の種類に限定されます:

  • アルファベット (a・・・z, A・・・Z)
  • 数字 (0・・・9)
  • ハイフン ("-")
  • アンダースコア ("_")

VTL で有効な変数リファレンスの例をいくつか示します。

$foo
$mudSlinger
$mud-slinger
$mud_slinger
$mudSlinger1

VTL が ($foo のような) 変数を参照する場合、変数の値を、テンプレートの set 指示子、または Java のコードから取得できます。例えば、テンプレートが要求された時に Java 変数$foo が値 bar を持っていれば、Web ページ上で $foo の全てのインスタンスが bar で置換できます。言い換えると、以下の文を入れると、

#set( $foo = "bar" )

この指示子以降の $foo の全てのインスタンスについて出力は同じになります。

プロパティ
VTL リファレンスの第二の形式はプロパティで、特徴的なフォーマットを持っています。簡略表記は、「$」とそれに続く VTL 識別子、それにドット「.」を挟んで続く別の VTL 識別子から成ります。 VTL での有効なプロパティリファレンスの例を示します:

$customer.Address
$purchase.Total

最初の例 ($customer.Address) の場合は、2つの意味が考えられます。一つは、customer で識別される hashtable を見て、キーAddress と関連づけられる値を返すという意味です。しかし、$customer.Address はメソッドを参照しているのかも知れないのです。 (メソッドを参照するリファレンスは、次のセクションで説明します)。$customer.Address は、$customer.getAddress() の省略表記でもあるのです。ページが要求されたとき、Velocity はこれらの2つの可能性のうちどちらが意味をなすかを判定して、適切な値を返します

メソッド
メソッドは Java コードにおいて定義されるもので、何か役に立つこと (計算や判定の実行など) を行うことができます。メソッドは「$」と、それに続く VTL 識別子と、それに続く VTLメソッドボディ (Method Body) から構成されるリファレンスです。 VTL メソッドボディは、VTL 識別子と、それに続く左括弧("(")、パラメータリスト (オプション)、それに右括弧(")")から構成されます。 VTL で有効なメソッドリファレンスの例を示します。

$customer.getAddress()
$purchase.getTotal()
$page.setTitle( "My Home Page" )
$person.setAttributes( ["Strange", "Weird", "Excited"] )

最初の2つの例 ($customer.getAddress()$purchase.getTotal()) は、上のプロパティのセクションで使われた例 ($customer.Address$purchase.Total) に類似しているように見えるかもしれません。これらの例は何か関係があるはずだと思ったら、それは正解です!

VTL プロパティは、VTL メソッドの簡略表記として使えます。プロパティ $customer.Address は、メソッド $customer.getAddress() を使うのと完全に同じ効果があります。一般に、利用可能ならプロパティを使う方が望ましいです。プロパティとメソッドの主な違いは、メソッドにはパラメータリストを指定できるということです。

簡略表記は、以下のメソッドで使うことができます。

$sun.getPlanets()
$annelid.getDirt()
$album.getPhoto()

こうしたメソッドは、太陽系の惑星の名前を返すとかミミズに餌をやるとか、アルバムから写真を取り出すといったことが想定されるでしょう。以下のメソッドは、長い表記だけが動作します。

$sun.getPlanet( ["Earth", "Mars", "Neptune"] )
## $sun.Planets にはパラメータリストを渡せません。
$sisyphus.pushRock()
## ($sisyphus.Rockだと) Velocity は $sisyphus.getRock() だと思ってしまいます。
$book.setTitle( "Homage to Catalonia" )
## パラメータリストは渡せません。

正式リファレンス表記
上で一覧として挙げた例では、リファレンスの簡略表記が使われました。しかし、リファレンスのための正式表記もあります。以下に例を示します。

${mudSlinger}
${customer.Address}
${purchase.getTotal()}

ほとんどすべての場合、リファレンスには簡略表記を使用することになりますが、正しく処理するために正式表記が必要となる場合があります。

例えば、動的に文を構築するのに、文で使われる名詞のベースとなる単語として$vice を使うとしましょう。誰かにベースとなる単語を選択させて、「Jack is pyromaniac.」あるいは「Jack is kleptomaniac.」という結果を生成します。こういう場合、簡略表記を使用するとまずいのです。以下の例を考えてみてください。

Jack is a $vicemaniac.

この表現は曖昧で、Velocity は識別子として、あなたが使いたい$viceではなく $vicemaniac を認識します。$vicemaniac の値は見つからないので$vicemaniac をそのまま返すことになります。正式表記を使用することで、この問題を解決できます。

Jack is a ${vice}maniac.

こうすれば Velocity は、$vicemaniac ではなく $vice がリファレンスであると認識します。正式表記が役に立つことが多いのは、このようにリファレンスがテンプレート中でテキストと隣接している時です。

沈黙リファレンス表記
Velocity が未定義のリファレンスに遭遇したとき、通常の挙動として、リファレンスの記述をそのまま出力します。例えば、以下のリファレンスが VTL テンプレートの一部に出てきたとしましょう。

<input type="text" name="email" value="$email"/>

最初にフォームがロードされるとき、変数のリファレンス $email には値がありませんが、テキストフィールドに「$email」という値が入っているよりブランクになっている方がよいでしょう。リファレンスの沈黙表記を使用することで、Velocity の通常の挙動を回避します。具体的には VTL で$email を使う代わりに、 $!email を使います。したがって、上記の例は以下のようになります:

<input type="text" name="email" value="$!email"/>

これで、最初にフォームがロードされて $email がまだ値を持たないとき、「$email」の代わりに空の文字列が出力されます。

リファレンスを正式表記かつ沈黙表記として使うことも出来ます。具体的には以下のようにします。

<input type="text" name="email" value="$!{email}"/>
 
リテラルを取得する

VTL は、「$」 や 「#」のように特殊文字を使用するので、テンプレート内でこれらの文字を使用する場合には注意が必要です。このセクションでは、「$」をエスケープする方法を説明します。

通貨
「私は市場で 4ポンドの袋入りのジャガイモをたった $2.50 で買いました!」と書くことについては問題はありません。 VTL 識別子は常に大文字または小文字の英字から始まるので、$2.50をリファレンスと間違えることはありません。

有効なVTLリファレンスをエスケープする
Velocity が混乱する可能性がある場合もあります。特殊文字のエスケープは、テンプレート内で VTL の特殊文字を扱う最適な方法であり、バックスラッシュ(\)を使って行えます。

#set( $email = "foo" )
$email

Velocity が VTL テンプレートで $email リファレンスを検出すると、対応する値を求めてコンテキストを検索します。ここでは、$email が定義されているので、出力はfoo になります。 $email が定義されていなければ、出力は $email になります。

(例えば値が foo である) $email が定義されていて、 $email と出力したい場合を考えてください。解決方法はいくつかありますが、最も単純なのはエスケープ文字を使うことです。

## このテンプレートでは、次の行で $email を定義しています。
#set( $email = "foo" )
$email
\$email
\\$email
\\\$email

これは以下のように処理されます。

foo
$email
\foo
\$email

左から「\」が「$」に結合することに注意してください。「左から結合する」規則の結果、 \\\$email を処理すると\\$email になります。上記の例を、下記の$email が定義されない例と比較してみてください。

$email
\$email
\\$email
\\\$email

これは以下のように処理されます。

$email
\$email
\\$email
\\\$email

Velocity は、定義されていない場合と定義されていない場合とで、リファレンスの扱いが異なることに注意してください。 以下の例では、set 指示子で $foo に値 gibbous をセットします。

#set( $foo = "gibbous" )
$moon = $foo

出力は$moon = gibbousになります ─ $moon は未定義なのでリテラルとして出力され、 $foo のところにはgibbous が出力されるのです。

VTL 指示子をエスケープすることも可能です; この詳細については、 指示子 セクションで説明します。

 
大文字小文字置換

リファレンスに慣れると、テンプレートで効果的にリファレンスを使えるようになります。 Velocity リファレンスでは Java の利点を生かしていますが、テンプレートデザイナでも使うのは難しくないと思います。例を挙げましょう。

$foo
$foo.getBar()
## 上と下は同じです
$foo.Bar
$data.getUser("jon")
## 上と下は同じです
$data.User("jon")
$data.getRequest().getServerName()
## 上と下は同じです
$data.Request.ServerName
## また、これも同じです
${data.Request.ServerName}

これらは、同じリファレンスのいろんな使い方の具体例です。 Velocity は、Java のイントロスペクション機能と Bean 機能を利用して、コンテキスト内のオブジェクトと、オブジェクトメソッドの両方のリファレンス名を解決します。テンプレート中のほぼどこにでもリファレンスを埋め込んで、評価することが可能です。

Velocity では、サンマイクロシステムズが策定した Bean 仕様書に元にモデルを作ったので、大文字と小文字を区別します。しかし、Velocity の開発者は、ユーザエラーを出来る限り検出して訂正するよう努力しました。getFoo() メソッドが、テンプレート内で$bar.foo によって参照されるとき、Velocityはまず $getfoo を試み、それに失敗すると、 $getFoo を試みます。同じように、テンプレートが $bar.Foo を参照するとき、 Velocity は最初に$getFoo() を試みて、それから getfoo() を試みます。

注意: テンプレート中のインスタンス変数への参照は解決されません。 JavaBean の getter/setter メソッドに対応する属性だけが解決されます。 (つまり、$foo.Name は、 Foo クラスのインスタンスメソッドであるgetName() としては解決されますが、 Foo のパブリックのインスタンス変数である Name としては解決されません。)

 
指示子

リファレンスを使うと、テンプレートのデザイナが Web サイト向けに動的に内容を生成できるのに対して、 指示子 (使いやすいスクリプト要素で、Java コードの出力を思い通りに操作するのに使えます) を使うと、 Web デザイナは真の意味で Web サイトの内容と見栄えを管理できるようになります。

#set

#set 指示子は、リファレンスの値をセットするのに使います。値は、変数リファレンスかプロパティリファレンスにセットされ、その際、以下に示すように丸括弧でくくります。

#set( $primate = "monkey" )
#set( $customer.Behavior = $primate )

左辺(LHS:Left Hand Side)は、変数リファレンスまたはプロパティリファレンスでなければなりません。右辺(RHS:Right Hand Side)は、以下のタイプのいずれかです:

  • 変数リファレンス
  • 文字列リテラル
  • プロパティリファレンス
  • メソッドリファレンス
  • 数値リテラル
  • 配列リスト (ArrayList)

以下は、上記タイプの各々の例です:

#set( $monkey = $bill )                        ## 変数リファレンス
#set( $monkey.Friend = "monica" )              ## 文字列リテラル
#set( $monkey.Blame = $whitehouse.Leak )       ## プロパティリファレンス
#set( $monkey.Plan = $spindoctor.weave($web) ) ## メソッドリファレンス
#set( $monkey.Number = 123 )                   ## 数値リテラル
#set( $monkey.Say = ["Not", $my, "fault"] )    ## 配列リスト

注意: 最後の例で [..] オペレータで定義された要素は ArrayList クラスで定義されているメソッドを使用してアクセスできます。したがって、例えば、$monkey.Say.get(0) を使って上記の最初の要素 ("Not") にアクセスできます。

右辺には単純な計算式を入れることもできます。

#set( $value = $foo + 1 )
#set( $value = $bar - 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )

右辺がnullとして評価されるプロパティやメソッドだった場合、 null値は左辺に代入されません。 null代入で既存のリファレンスをコンテキストから削除することはできません。これはVelocity初心者には混乱の元となるかもしれません。例えば、

#set( $result = $query.criteria("name") )
最初のクエリの結果は $result です。
#set( $result = $query.criteria("address") )
2番目のクエリの結果は $result です。

$query.criteria("name") が "bill" という文字列を返し、 $query.criteria("address")null を返す時、上のVTLは次のように処理されます:

最初のクエリの結果は bill です。
2番目のクエリの結果は bill です。

このため、初心者が#foreach を使って、プロパティやメソッドリファレンスを別のリファレンスに #set し、直後にそのリファレンスを#if 指示子でテストする、というループを構築すると混乱しやすいでしょう。例えば、

#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = $query.criteria($criterion) )
#if( $result )
クエリは成功しました。
#end
#end

上の例において、クエリが成功したかどうかを判定するのに $result の評価を信頼するのは賢明とはいえません。 $result#set された(コンテキストに追加された)後、これを null に戻す(コンテキストから削除される)ことはできないのです。 #if#foreach の各指示子についてはこの文書で後述します。

これに対する解決法の一つは、事前に $resultfalse にセットしておくことです。そうすれば、 $query.criteria() の呼び出しが失敗した場合、チェックすることができます。

#set( $criteria = ["name", "address"] )
#foreach( $criterion in $criteria )
#set( $result = false )
#set( $result = $query.criteria($criterion) )
#if( $result )
クエリは成功しました。
#end
#end

他の Velocity 指示子のいくつかとは異なり、#set 指示子には #end 文がありません。

文字列リテラル

#set 指示子を使うとき、二重引用符(「"」)で囲まれた文字列リテラルは、以下に示すようにパース/処理されます。

#set( $directoryRoot = "www" )
#set( $templateName = "index.vm" )
#set( $template = "$directoryRoot/$templateName" )
$template

出力はこうなります

www/index.vm

しかし、文字列リテラルが単一引用符 (「'」) で囲まれている場合にはパースされません。

#set( $foo = "bar" )
$foo
#set( $blargh = '$foo' )
$blargh

この処理結果は、こうなります

  bar
$foo

単一引用符を使ってテキストをパースせずに処理するという機能は、 Velocity ではデフォルトで利用できます。このデフォルトは、velocity.properties を編集してstringliterals.interpolate=false とすることによって変更できます

 
If-Else 文

If / ElseIf / Else

Velocity の #if 指示子を使えば、if 文の条件が真という条件文で、 Web ページの生成時にテキストを含むようにできます。例を挙げましょう。

#if( $foo )
<strong>Velocity!</strong>
#end

変数 $foo が評価されて true かどうか判定されます。 true であるとは以下の2つの状況を指します。
(i) $foo が true の値を持つ boolean (true/false) の場合
(ii) $foo の値が null ではない場合
です。 Velocity のコンテキストはオブジェクトのみを保持することを思い出してください。「boolean」という場合、それは(クラスである)Booleanを意味します。これはboolean を返すメソッドに対しても当てはまり、内部的には同じ論理値の Boolean を返します。

#if#end の間の内容は、評価値が true の場合に出力されます。この場合、$foo が true ならば、出力は「Velocity!」となります。逆に、$foo が null または、boolean で false ならば、文の評価は false となり、出力はありません。

#elseifまたは#else要素は #if要素と組で使用できます。 Velocity テンプレートエンジンは、最初に式が true になったところで評価を止めることに注意してください。下記の例で、$foo が 15 という値を持ち、$bar は 6 という値を持つとします。

#if( $foo < 10 )
<strong>Go North</strong>
#elseif( $foo == 10 )
<strong>Go East</strong>
#elseif( $bar == 6 )
<strong>Go South</strong>
#else
<strong>Go West</strong>
#end

この例では、$foo は、10 より大きいので最初の 2 つの比較は失敗します。次に、$bar が、6 と比較され、それが true なので、出力はGo South となります。

注意: 現在、Velocity の数値の比較は Integer のみ行えます ─ それ以外の場合には false と評価します。これに対する唯一の例外は等号「==」です。その場合、「==」の両辺のオブジェクトは、同じクラスである必要があります。

関係演算子と論理演算子

Velocity は、変数の関係を決定するために等価演算子を使います。等価演算子の使い方の単純な例を示します。

#set ($foo = "deoxyribonucleic acid")
#set ($bar = "ribonucleic acid")
#if ($foo == $bar)
この場合、等価でないことは明らかなので…
#else
等価でないので、こちらが出力されます。
#end

Velocity には、この他に AND/OR/NOT という論理演算子があります。 詳細な情報については、 VTL Reference Guide をご覧下さい。 以下は、論理演算子 AND/OR/NOT を使用した例です。

## 論理 AND
#if( $foo && $bar )
<strong>これ AND あれ</strong>
#end

#if() 指示子は、$foo$bar が共に true かどうか、評価します。 $foo が false ならば、式全体は false に評価され$bar は、評価されません。 $foo が true ならば、Velocity テンプレートエンジンは、次に $bar の値をチェックします。$bar が true ならば、式全体が、true となって これ AND あれ が出力されます。 $bar が false ならば、式全体が false となって出力されません。

論理演算子 OR も同様ですが、式全体が true になるには true と評価されるリファレンスが1つだけあればよいというところだけが違います。以下の例を考えてみてください。

## 論理 OR
#if( $foo || $bar )
<strong>これ OR あれ</strong>
#end

$foo が true ならば、Velocity テンプレートエンジンは $bar を調べる必要はありません。 $bar が true であるか false であるかどうかに関係なく、式は true となり、 これ OR あれ が出力されます。$foo が false ならば、今度は $bar をチェックしなければなりません。この場合、$bar も false ならば、式は false と評価して、出力はありません。一方、$bar が true ならば、式全体が true になり、出力はこれ OR あれ となります。

論理演算子 NOT では、引数は1つしかありません。

## 論理 NOT
#if( !$foo )
<strong>NOT あれ</strong>
#end

ここで、 $foo が true であれば、 !$foo は false と評価され、出力はありません。 $foo が false であれば、!$foo は true と評価されて、 NOT あれ が出力されます。これを 沈黙リファレンスの $!foo と混同しないように注意してください。全然違うものですから。

 
#foreach ループ

Foreach Loop

#foreach 要素を使うとループ処理ができます。例えば

<ul>
#foreach( $product in $allProducts )
<li>$product</li>
#end
</ul>

この #foreach ループによって、$allProducts リスト (オブジェクト) で製品(ターゲット)の全てについてループが行われます。ループの一回一回で$allProducts からの値が $product 変数にセットされます。

$allProducts 変数の内容は、Vector、Hashtable、配列のいずれかです。 $product 変数に割り当てられる値は、Java オブジェクトで、 Java オブジェクトのように変数から参照できます。たとえば、もし$product が本当に Java の Product クラスならば、その名前は、$product.Name メソッド (=$Product.getName()) で参照して取り出すことができます。

$allProduct が Hashtable だとしましょう。もし Hashtable から、キーの値と Hashtable 内のオブジェクトを取り出したい場合には、次のようにコードを使用します。

<ul>
#foreach( $key in $allProducts.keySet() )
<li>Key: $key -> Value: $allProducts.get($key)</li>
#end
</ul>

Velocity ではループカウンタを簡単に取得できるので、次のようなことができます。

<table>
#foreach( $customer in $customerList )
<tr><td>$velocityCount</td><td>$customer.Name</td></tr>
#end
</table>

ループカウンタ変数リファレンスのデフォルト名は、velocity.properties ファイルに指定されている通り、$velocityCount です。カウンタはデフォルトでは 1 から開始しますが、velocity.properties ファイルで 0 か 1 のどちらかに設定できます。velocity.properties ファイルのループカウンタプロパティセクションの内容を以下に示します。

# ループカウンタ変数リファレンスのデフォルト名
directive.foreach.counter.name = velocityCount
# ループカウンタ変数リファレンスのデフォルト開始値
directive.foreach.counter.initial.value = 1
 
#include

#include スクリプト要素でローカルファイルをインポートできます。ファイルは #include 指示子が定義される位置に挿入されます。ファイルの中身は、テンプレートエンジンによって処理されません。セキュリティ上の理由から、インクルードされるファイルは、 TEMPLATE_ROOT 以下にあるものだけが許されます。

#include( "one.txt" )

#include 指示子が参照するファイルは、引用符で囲まれます。複数のファイルをインクルードする場合には、それらをコンマで区切ります。

#include( "one.gif","two.txt","three.htm" )

インクルードされるファイルを名前で参照する必要はありません。実際、多くの場合ファイル名の代わりに変数を使うことが望ましいです。これは、ページ要求があったときに、事前に決めた基準にしたがって出力を切り替えるのに役立ちます。これは、ファイル名と変数両方を使用した例です。

#include( "greetings.txt", $seasonalstock )
 
#parse

#parse スクリプト要素で VTL を含むローカルファイルをインポートできます。 Velocity は、VTL を解析し、指定されたテンプレートを処理します。

#parse( "me.vm" )

#include 指示子と同じく、#parse はテンプレートの代わりに変数をとることができます。 #parse が参照するテンプレートはすべて、TEMPLATE_ROOT 以下になければなりません。#include 指示子と違って、#parse の引数は一つだけです。

VTL テンプレートは、#parse 文で参照するテンプレート内でさらに #parse 文で [別のテンプレートを] 参照できます。単独のテンプレートでの#parse 参照による入れ子の回数の最大値はデフォルトで10にセットされていて、 velocity.propertiesparse_directive.maxdepth 行で、カスタマイズできます。 (注: parse_directive.maxdepth プロパティがvelocity.properties ファイルになければ、Velocity がこのデフォルトを 10 にセットします。) 再帰も可能です。例えばテンプレートdofoo.vm が以下の行を含む場合、

カウントダウン。
#set( $count = 8 )
#parse( "parsefoo.vm" )
dofoo.vm の処理完了!

このコードは以下の VTL の内容のテンプレート parsefoo.vm を参照します。

$count
#set( $count = $count - 1 )
#if( $count > 0 )
#parse( "parsefoo.vm" )
#else
parsefoo.vm の処理完了!
#end

「カウントダウン。」が表示された後、 Velocity は parsefoo.vm を走査し、8 からカウントダウンします。カウントが 0 に達すると、「parsefoo.vm の処理完了!」メッセージを表示します。この時点で、Velocity はdofoo.vm に戻って、「dofoo.vm の処理完了!」メッセージを出力します。

 
#stop

#stop スクリプト要素でテンプレートエンジンの実行を止めることができます。これは、デバッグするときに役立ちます。

#stop
 
Velocimacro

#macro スクリプト要素で、VTL テンプレートで繰り返し出てくる部分を定義できます。 Velocimacro は、単純なものから複雑なものまで広範囲にわたるシナリオで非常に役立ちます。次の Velocimacro は、キーストロークを節約し、入力ミスを少なくするためだけに作られたものですが、 Velocimacro の概念を紹介するのに役立つでしょう。

#macro( d )
<tr><td></td></tr>
#end

この例で定義されている Velocimacro は d です。そして、それは他の VTL 指示子 と同じような方法で呼び出すことができます:

#d()

このテンプレートが呼ばれると、Velocity は #d() を一つの、空のデータセルを含んでいる列と置換します。

Velocimacro は任意の数の引数を取ることが出来ます (最初の例で示したとおり引数なしでもかまいません)。ただし、Velocimacro が呼び出されるとき、定義されたのと同じ数の引数で呼ばれなければなりません。多くの Velocimacro は、上で定義したものより多くの引数を含みます。これは、色と配列という2つの引数をとる Velocimacro です。

#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end

この例(tablerows)で定義されている Velocimacro は、2つの引数をとります。最初の引数は、$color となり、2番目の引数は、$somelist となります。

VTL テンプレートに入れられるものは何でも、Velocimacro の本体に入れることができます。 tablerows Velocimacro は、foreach 文です。 2つの#end 文が、#tablerows Velocimacro の定義にありますが、最初の end で #foreach が終了し、二番目の end で Velocimacro 定義が終了します。

#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>

$greatlakes$somelist に代わることに注意してください。 #tablerows Velocimacro が上記のように呼ばれるとき、以下の出力が生成されます。

<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>

Velocimacro は Velocity テンプレート内で インライン で定義できますが、その場合は同じ Web サイトの他の Velocity テンプレートには利用できません。全てのテンプレートで共有できるような Velocimacro を定義することには、明らかにいくつかの利点があります。例えば、多数のテンプレートで Velocimacro をいちいち定義する必要を減らせますし、それにより作業量が節約されたり、エラーの可能性が減りますし、一つのマクロに対する一箇所の変更が複数のテンプレートに反映されることを保証します。

#tablerows($color $list) Velocimacro が Velocimacro テンプレートライブラリで定義されている場合、このマクロはどの通常のテンプレートでも使うこともできます。それは、何度でも使えますし、どんな用途でも使うことが出来ます。菌類百科専門のmushroom.vm テンプレートの中で、 #tablerows Velocimacro は、典型的なキノコの各部分をリストするために呼び出すことができます:

#set( $parts = ["volva","stipe","annulus","gills","pileus"] )
#set( $cellbgcol = "#CC00FF" )
<table>
#tablerows( $cellbgcol $parts )
</table>

mushroom.vm の要求を満たすとき、Velocity は #tablerows Velocimacro をテンプレートライブラリ (velocity.properties ファイルにおいて定義されています) から見つけて、以下の出力を生成します。

<table>
<tr><td bgcolor="#CC00FF">volva</td></tr>
<tr><td bgcolor="#CC00FF">stipe</td></tr>
<tr><td bgcolor="#CC00FF">annulus</td></tr>
<tr><td bgcolor="#CC00FF">gills</td></tr>
<tr><td bgcolor="#CC00FF">pileus</td></tr>
</table>

Velocimacro 引数

Velocimacro は、以下の VTL 要素のどれでも引数として取ることができます。

  • リファレンス : 「$」で始まる全て
  • 文字列リテラル : "$foo" や 'hello'のようなもの
  • 数値リテラル : 1, 2 など
  • 整数範囲 : [1..2] や [$foo .. $bar]
  • オブジェクト配列 : ["a", "b", "c"]
  • boolean 値の true
  • boolean 値の false

Velocimacro の引数としてリファレンスを渡す際、リファレンスは「名前渡し」されることに注意してください。つまり、Velocimacro 内で使われるたびにその値が「生成される」ことを意味します。この機能を使って、リファレンスにメソッド呼び出しを渡して、使うたびにそのメソッドを呼ぶようにできます。例えば、以下に示すように Velocimacro を呼び出すと、

     #macro( callme $a )
$a $a $a
#end
#callme( $foo.bar() )

結果として、リファレンス $foo のメソッド bar() が3回呼び出されます。

一見、この機能は驚くべきことのように見えます、しかし、あなたが Velocimacro の背景にある最初の動機 ― よく使われる VTL をカット&ペーストすることによる重複を除去する ― を考慮すれば、納得できるかと思います。この機能により、 Velocimacro に「状態を保持する」(Stateful) オブジェクト (例えばテーブル列に色をつけるために繰り返しシーケンスで色を生成するオブジェクト) を渡すようなことができます。

この機能を回避する必要があるならば、常にメソッドから値をリファレンスとして取得し、それを渡せばよいのです。

     #set( $myval = $foo.bar() )
#callme( $myval )

Velocimacro プロパティ

velocity.propertiesファイル内の何行かを使えば、Velocimacro を柔軟に実装できます。注意: 開発者ガイドも参照してください。

velocimacro.library ─ 全ての Velocimacro テンプレートライブラリのコンマ区切りリスト。デフォルトでは、Velocity はVM_global_library.vm というライブラリのみを探します。設定されたテンプレートパスは Velomacro ライブラリを見つけるのに使用されます。

velocimacro.permissions.allow.inline ─ このプロパティは true または false の値を取ることができ、 Velocimacro を通常のテンプレートで定義できるかどうか判定します。デフォルト (true) では、テンプレートで Velocimacro を定義できます。

velocimacro.permissions.allow.inline.to.replace.global ─ このプロパティは true または false の値を取ることができ、テンプレート内でインラインで定義された Velocimacro がグローバルで定義されたテンプレート (スタートアップ時にvelocimacro.library プロパティ経由でロードされたもの) を上書きできるかどうかを指定します。デフォルトではfalse なので、スタートアップでロードされたテンプレートライブラリで定義されたものはインラインの Velocimacro では上書きできません。

velocimacro.permissions.allow.inline.local.scope ─ このプロパティは true または false の値を取ることができ、デフォルトは false です。インラインで定義された Velocimacro が、定義したテンプレートでだけ「見える」かどうかを制御します。つまり、このプロパティを true にすると、定義されたテンプレート内でのみ有効なインライン VM を定義することが出来ます。これを使った、手の込んだ VM のテクニックがあります。グローバルな VM が別のグローバルな VM を呼ぶ場合、テンプレートはインラインスコープで、前者の VM から呼ばれる後者の VM のプライベート実装を定義できます。他のどのテンプレートにも影響ありません。

velocimacro.context.localscope ─ このプロパティは true または false の値を取ることができ、デフォルトは false です。 true のときは、Velocimacro 内の #set() によるコンテキストへの変更はすべて、 Velocimacro に「ローカル」であると扱われて、コンテキストに永続的な影響を及ぼしません。

velocimacro.library.autoreload ─ このプロパティは Velocimacro の自動ロードを制御します。デフォルトの値はfalse です。 true にセットされると、呼び出された Velocimacro に対応する Velocimacro ライブラリのソース変更がチェックされ、必要に応じてリロードされます。これにより、ちょうど普通のテンプレートでできるように、アプリケーションやサーブレットコンテナを再起動せずに Velocimacro ライブラリを変更、テストすることができます。このモードはリソースローダーでキャッシングをoff にした時 (例えば file.resource.loader.cache = false にした時) だけ有効です。この機能は開発用で、本番環境用ではありません。

Velocimacro まめ知識

現在、Velocimacro はテンプレートで最初に使われる前に定義されていなければなりません。つまり、 #macro() 宣言が Velocimacro を使う前に出てくる必要があります。

インラインの #macro() 指示子を含んでいるテンプレートを #parse() しようとするときには、このことに気をつける必要があります。というのも、 #parse() は実行時に発生し、パーサはテンプレート中の VM のように見える要素が VM かどうかをパース時に判定するため、 VM 宣言を #parse() しても期待したようには動かないのです。これを回避するには、単にvelocimacro.library 機能を使ってください。 Velocity はあなたの VM を起動時にロードします。

 
VTL 指示子をエスケープする

VTL 指示子は、VTL リファレンスと同様に、バックスラッシュ (「\」) でエスケープできます。

## #include( "a.txt" ) は <a.txtの内容> として処理される
#include( "a.txt" )
## \#include( "a.txt" ) は \#include( "a.txt" ) として処理される
\#include( "a.txt" )
## \\#include ( "a.txt" ) は \<a.txt の内容> として処理される
\\#include ( "a.txt" )

一つの指示子に複数のスクリプト要素が含まれている VTL 指示子 (if-else-end 文など)をエスケープする時は、特に注意が必要です。典型的な VTL の if 文は以下のようなものです:

#if( $jazz )
Vyacheslav Ganelin
#end

$jazz が true ならば、出力は です。

$jazzが false ならば、出力はありません。スクリプト要素をエスケープすると、出力が変わります。以下の場合を考えてみましょう。

\#if( $jazz )
Vyacheslav Ganelin
\#end

$jazzが ture か false かどうかに関係なく、出力は、

#if($ jazz )
Vyacheslav Ganelin
#end

実際、全てのスクリプト要素がエスケープされるので、$jazz の真偽は決してチェックされません。バックスラッシュが正しくエスケープされたスクリプト要素の前にあるとしましょう。

\\#if( $jazz )
Vyacheslav Ganelin
\\#end

この場合、$jazzが true ならば、出力は

\ Vyacheslav Ganelin
\

となります。

これを理解するためには、#if( arg ) が改行(return) で終了しているときに、その改行は出力から除外されることに着目してください。そのため、#if() ブロックのボディが最初の「\」 (#if() とその前の 「\\」 の処理結果)に続きます。最後の「\」は別の行になっています。それは、「Ganelin」の後に改行があり、#end の前にある最後の \\ は、ブロックのボディの一部であるためです。

$jazzが false ならば、出力はありません。 [訳注:実際には、#if( arg ) とその前の「\\」の処理結果である「\」だけが出力されます。] スクリプト要素が適切にエスケープされていなけば、おかしくなることに注意してください。

\\\#if( $jazz )
Vyacheslave Ganelin
\\#end

ここでは、#if はエスケープされますが、#end が残っています。 end が余分なので、解析エラーを引き起こすことになります。

 
VTL のフォーマット

このユーザガイドの中の VTL は多くの場合、下記のように改行と空白を含んで表示されています。

#set( $imperial = ["Munetaka","Koreyasu","Hisakira","Morikune"] )
#foreach( $shogun in $imperial )
$shogun
#end

Geir Magnusson Jr. は、改行や空白が全く無関係というのを示すために Velocity ユーザのメーリングリストに次のようなコードを投稿しました。

Send me #set($foo = ["$10 and ","a cake"])#foreach($a in $foo)$a #end please.

Velocity は、余分な空白を吸収するように振舞います。上の指示子は以下のように書くことができます:

Send me
#set( $foo = ["$10 and ","a cake"] )
#foreach( $a in $foo )
$a
#end
please.

または

Send me
#set($foo       = ["$10 and ","a cake"])
#foreach           ($a in $foo )$a
#end please.

どちらの場合も出力は同じです。

 
その他の機能
Math

Velocity には一握りですが組み込みの計算機能があり、テンプレートのset 指示子で使うことができます。以下の式は、それぞれ加算、減算、乗算、除算の例です。

#set( $foo = $bar + 3 )
#set( $foo = $bar - 4 )
#set( $foo = $bar * 6 )
#set( $foo = $bar / 2 )

除算が実行される場合も結果は整数となります。余りについては剰余演算子 (「%」) を使って取得できます。

#set( $foo = $bar % 5 )

Velocity で数式演算を実行する時は、整数だけ(...-2、-1、0、1、2...)が許可されており、非整数が使われるとログに記録され、null が出力として返されます。

 
範囲演算子

範囲演算子は、#set#foreach 文と一緒に使うことができます。要素に整数を持つオブジェクト配列を生成するのに役立つ範囲演算子は、次のように生成できます。

[n..m]

nm は両方とも整数であるか、整数を生成しなければなりません。 m が、n より大きいか、小さいかは重要ではありません; より小さい場合には、範囲は単にカウントダウンします。下記は範囲演算子の使い方を示している例です。

例1:
#foreach( $foo in [1..5] )
$foo
#end
例2:
#foreach( $bar in [2..-2] )
$bar
#end
例3:
#set( $arr = [0..1] )
#foreach( $i in $arr )
$i
#end
例4:
[1..3]

以下の出力を生成します:

例1:
1 2 3 4 5
例2:
2 1 0 -1 -2
例3:
0 1
例4:
[1..3]

4番目の例が示しているとおり、範囲演算子は #set#foreach 指示子とともに使われた時だけ配列を生成することに注意してください。

HTMLの表を決まったサイズにしたいのに、表を埋めるにはデータが足りないこともあります。そんな時、範囲演算子は特に便利です。

 
高度な問題: エスケープと 「!」

リファレンスを「!」で沈黙させていて、「!」の前に「\」エスケープ文字があるときは、リファレンスは特別扱いされます。通常のエスケープと、「\」に「!」が続く特別な場合の違いに注意してください。

#set( $foo = "bar" )
$\!foo
$\!{foo}
$\\!foo
$\\\!foo

これは以下のように処理されます。 [訳注: 2行目は実際には「$!{」となります。]

$!foo
$!{foo}
$\!foo
$\\!foo

これを、「\」が「$」に先行する、通常のエスケープと比較してみましょう。

\$foo
\$!foo
\$!{foo}
\\$!{foo}

これは以下のように処理されます。

$foo
$!foo
$!{foo}
\bar
 
Velocimacro いろいろ

このセクションは、Velocimacro に関するミニ FAQ です。このセクションは、時とともに変更されるでしょう、ですから新しい情報を時々確認するのは有用です。 [訳注:このバージョンでは変更されませんが、次のバージョンでは変更されているかもしれません]

注意: このセクションでは、「Velocimacro」は通常「VM」と略します。

VM の引数として指示子や他の VM を使用できますか?

例 : #center( #bold("hello") )

いいえ。指示子は指示子の有効な引数にはなりません。また、一般的に、 VM は指示子です。

それでも…、解決策はあります。簡単なものとして、ダブルクォート (") がその内容を処理することを利用する方法があります。なので、このようにできます。

#set($stuff = "#bold('hello')" )
#center( $stuff )

以下のように省略も可能です…

#center( "#bold( 'hello' )" )

注意: 後者の例では、引数は VM 内部で評価されます。呼び出し時ではありません。言い換えると、VM への引数は、そっくりそのまま渡されて、渡された VM の中で評価されます。その結果、次のようなことが可能です。

#macro( inner $foo )
inner : $foo
#end
#macro( outer $foo )
#set($bar = "outerlala")
outer : $foo
#end
#set($bar = 'calltimelala')
#outer( "#inner($bar)" )

ここで出力は以下のようになります。

outer : inner : outerlala

"#inner($bar)" の評価は、#outer() の内部で発生するため、 $bar の値としては #outer() 内部でセットされたその値が使われます。

この機能は意図的なものであり、十分に保護されています ─ 引数は VM に「名前渡し」されるので、以下のように、「状態を保持する」(Stateful) リファレンスなどを VM に渡すことが出来ます。

#macro( foo $color )
<tr bgcolor=$color><td>Hi</td></tr>
<tr bgcolor=$color><td>There</td></tr>
#end
#foo( $bar.rowColor() )

また、rowColor() は1回ではなく、[#foo() の呼び出しごとに] 何度も呼ばれます。これを禁止するには、 VM の外側でメソッドを呼び出し、 VM には値を渡してください。

#set($color = $bar.rowColor())
#foo( $color )

#parse() を使って Velocimacro を登録できますか ?

現在、Velocimacro はテンプレートで最初に使われる前に定義されていなければなりません。つまり、 #macro() 宣言が Velocimacro を使う前に出てくる必要があります。

インラインの #macro() 指示子を含んでいるテンプレートを #parse() しようとするときには、このことに気をつける必要があります。というのも、 #parse() は実行時に行われ、パーサは、テンプレート内の VM のように見える要素が VM かどうかをパース時に決定するため、 VM の宣言を #parse() しても期待したようには動かないのです。これを回避するには、単にvelocimacro.library 機能を使ってください。 Velocity はあなたの VM を起動時にロードします。

Velocimacro 自動再ロードとは ?

そのためのプロパティがあります。これは開発時に使用するためのもので、本番環境用ではありません。

velocimacro.library.autoreload

デフォルトは、 false です。 true にセットする時は、下記の指定と一緒に使います。

<type>.resource.loader.cache = false

(ここで、 <type> は、'file' など使用するリソースローダの名前です) そうすると Velocity エンジンは、自動的にあなたの Velocimacro ライブラリファイルが変更されたときに変更をリロードしようとします。そのため、サーブレットエンジン (あるいはアプリケーション) を再起動したり Velocimacro をリロードするために小細工をする必要はありません。

簡単なプロパティ設定はこのようになります。

    file.resource.loader.path = templates
file.resource.loader.cache = false
velocimacro.library.autoreload = true

本番環境ではこの状態のままにしておかないでください。

 
文字列の連結

開発者共通の疑問として、「文字列の連結はどうするのか?Javaにおける '+' 演算子のようなものがあるのか?」というのがあります。

VTLにおいてリファレンスの結合を行うには、単に「並べて記述する」だけです。並べて記述するといっても状況によりますので、いくつかの例を使って示します。

テンプレートの一般的な「シュムー」[訳注:VTL 以外の部分]において(一般的な内容に混ぜる時)、

       #set( $size = "Big" )
#set( $name = "Ben" )
その時計は $size$name.

出力は「その時計は BigBen.」と処理されます。もうすこし面白い例として、メソッドに渡すために文字列を結合したい場合や新しいリファレンスにセットしたい場合は以下のようにします。

      #set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "$size$name" )
その時計は $clock.

結果として同じ出力になります。最後の例として、リファレンスを「静的な」文字列と混ぜたい場合、「正式リファレンス」を使う必要があるかもしれません。

      #set( $size = "Big" )
#set( $name = "Ben" )
#set($clock = "${size}Tall$name" )
その時計は $clock.

出力は「その時計は BigTallBen.」になります。正式表記はパーサに「$sizeTall」ではなく「$size」リファレンスを使うということを知らせるのに必要です。「{}」がないと「$sizeTall」になってしまいます。

Velocity ユーザガイド相关推荐

  1. 卡尔曼滤波— Constant Velocity Model

    假设你开车进入隧道,GPS信号丢失,现在我们要确定汽车在隧道内的位置.汽车的绝对速度可以通过车轮转速计算得到,汽车朝向可以通过yaw rate sensor(A yaw-rate sensor is ...

  2. aa bb ccc java,TinyTemplate(Velocity Plus版)即将火热推出~~~

    原本是没有本身写一个模板引擎的计划的,由于按个人理解,一直认识这种"语言"级的引擎,难度是很是大的.总感受本身的水平不够,所以不敢有这个念头.直到大量使用Velocty的时候,碰到 ...

  3. Velocity 入门(一)

    Velocity是一种Java模版引擎技术,该项目由Apache提出.因为非常好用,和工作中有啥用,所以我在在理简单的入门一下. 网上找了很多教程,写的不是很明白,要么就是全部拷贝下来时候运行不起来. ...

  4. spring mvc velocity 配置备忘

    2019独角兽企业重金招聘Python工程师标准>>> Spring里面最重要的概念是IOC和AOP,还有两项很重要的模块是事务和MVC,对于IOC和AOP,我们要深究其源码实现,对 ...

  5. Velocity判断空的方法

    Velocity中没有null,那么怎么判断null呢 1.在velocity中,非null被认为是真的,所以,可以如下用: #if($!变量名)// 变量不为空的代码 #else// 变量为空的代码 ...

  6. Velocity文档(3)

    2019独角兽企业重金招聘Python工程师标准>>>     velocity.properties 的一些配置项 velocimcro.library属性:指定自己的模板库,多个 ...

  7. velocity自定义标签和指令

    velocity本身支持自定义标签和指令的扩展, 在 Velocity 模板语言的语法中,以美元符 $ 开头的为变量的声明或者引用,而以井号 # 开头的语句则为 Velocity 的指令(Direct ...

  8. java中velocity定义宏标签_velocity自定义标签和指令(转:zwj)

    velocity本身支持自定义标签和指令的扩展,我们看看扩展指令的步骤及searchweb2的应用场景, 1.使用方法 在 Velocity 模板语言的语法中,以美元符 $ 开头的为变量的声明或者引用 ...

  9. Velocity笔记--使用Velocity获取动态Web项目名的问题

    以前使用jsp开发的时候,可以通过request很轻松的获取到根项目名,现在换到使用velocity渲染视图,因为已经不依赖servlet,request等一些类的环境,而Web项目的根项目名又不是写 ...

  10. freemarker中运算符_如何在Web应用系统表示层开发中应用Velocity模板技术

    软件项目实训及课程设计指导--如何在Web应用系统表示层开发实现中应用Velocity模板技术 1.分离Web表示层的数据处理和展现逻辑的常见的应用技术 分离Web表示层的数据处理和展现逻辑是目前企业 ...

最新文章

  1. 用Python玩转PPT!
  2. Java8 中有趣酷炫的小技巧,你用到了那些?
  3. python字典数据类型笔记_Python学习笔记整理(六)Python中的字典
  4. java 调用word插件_java一键生成word操作,比poi简单
  5. BZOJ1598: [Usaco2008 Mar]牛跑步
  6. java设计模式简述
  7. python广告搞笑_技术入门 | 听说Python的广告刷爆了你的朋友圈?
  8. CONFIGURE RETENTION POLICY
  9. [vue] vue组件会在什么时候下被销毁?
  10. 草稿-git的使用-for windows -1006
  11. linux内核部件分析(十)——设备驱动模型之class,linux内核部件分析(十)——设备驱动模型之class...
  12. C++入门复习指南,C++Primer读书笔记
  13. Helpful links
  14. 计算机无法检测电池损耗怎么办,笔记本电脑电池损耗怎么修复 笔记本电脑电池损耗修复方法...
  15. Seek Tiger一级市场的王牌,基于web3.0概念的聚合平台强势来袭
  16. LWN:让内核支持符合FIPS规范的随机数!
  17. 企业如何提高客户转化率、复购率?用快鲸scrm效果突出
  18. 拓嘉辰丰电商:拼多多旗舰店有哪些优势,该怎么开?
  19. 启动gazebo失败报错[gazebo-1] process has died [pid 10999, exit code 255
  20. Mac系统使用终端检测局域网内开放端口的设备ip,扫描本地网络上的监控摄像头

热门文章

  1. IIS配置.net core出现的错误代码(0x80070005、0x8007000d、IIS Error 502.5)的解决办法
  2. MTK平台NV的功能与操作
  3. 终于有人把房价和汇率的关系讲清了!
  4. Java进阶—函数式接口
  5. 全网最全的Java岗IO流面试题(含答案)
  6. 视频教程-AR增强现实_AR小精灵视频课程-Unity3D
  7. 如何获取某个标签下所有的元素id_HTML文档元素的属性介绍
  8. 假设有一个英文文本文件,编写程序读取其内容,并将其中的大写字母变为小写字母,小写字母变为大写字母。
  9. Swagger-springFox3.0使用教程
  10. JS - 实现全角字符转半角字符处理