新トップページへ | Tip

velocityを使ってみる

LastUpdate : 11/11/03

 apache velocityとはJava用テンプレートエンジンのライブラリです。
ひょんなことから使うことになったので、その使い方をメモします。

Velocityjはなんだか、いろいろ機能がある様子ですが個人的主観で、必要だと思う部分のみ抜粋してメモしてます。

☆もくじ

  1. 動作環境とか
  2. 基本的なサンプル
  3. VTLについて


動作環境とか

今回のメモを作るにあたり、以下の環境で試しました。

開発環境 jdeveloper11.1.1.5.0
velocityのバージョン 1.7

以下のページから、velocityのjarをDLします。

http://http://velocity.apache.org/

jarがいくらか含まれています。トップディレクトリに、二つvelocityのjarがありますが、以下のように使い分けろってことらしい(「WHY_TWO_JARS.txt」に説明が書いてあります)。

jar名 説明
velocity-1.7.jar velocityのjarのほかに、依存関係のあるjarが実行には必要。
必要なjar:
 (1) Jakarta Commons Collections
 (2)Jakarta Commons Lang
 (3) Excalibur (ex-Avalon) Logkit
 (4) Jakarta ORO
(1)(2)は必須。(3)(4)は必須ではないが無いと実現できない機能がある。
(これについては「developer-guide.html」に書いてあります。)
velocity-1.7-dep.jar 依存するほかのjarも含めてセットになってる。これ一個使えばvelocity使えるよ!

(1)〜(4)のjarも、ダウンロードファイルに含まれています。

基本的なサンプル

テンプレートファイルを作成します。
このテンプレートファイルはVTLという言語で記述します。

sample1.vm
「$msgObj.name」さんのお金使用状況

今月のお給料 : $msgObj.salary円
今月のお出費 : $msgObj.expense円

ひゃっはー金がないぜ!

上記テンプレートを元に、以下のようにvelocityを利用し、文字列を生成します。以下のクラスを「new VelocitySample().main()」で呼んでやれば動きます

VelocitySample.java
import java.io.StringWriter;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

/**
 * apache Velocityを使用するに当たり以下のjarが必要
 *
 * Avalon-logkit-2.1.jar
 * Commons-collections-3.2.1.jar
 * Commons-lang-2.4.jar
 * Oro-2.0.8.jar
 * Velocity-1.7.jar
 */
public class VelocitySample {
    
    /** テンプレートファイルがあるディレクトリのパス */
    private static String TEMPLATE_FILE_DIRECTORY = "D:/dev/jdev/default/mywork/JavaProgram/template";
    
    public void main() {
        StringWriter writer = new StringWriter();
        MessageBucket msg = new MessageBucket("わんわんお", 100, 1000);
        
        try {
            /* Velocityの初期化前に、必要な設定をVelocityに対し設定してあげる */
            // テンプレートファイルのあるディレクトリを指定する(指定しない場合、現在のディレクトリになるっぽい)
            Velocity.setProperty("file.resource.loader.path", TEMPLATE_FILE_DIRECTORY);
            
            // Velocityの初期化
            Velocity.init();
            // コンテキストを生成
            VelocityContext context = new VelocityContext();
            context.put("msgObj", msg);
            
            // テンプレートを作成
            Template tmplate = Velocity.getTemplate("sample1.vm", "MS932");
            // データを生成し、結果をwriterに出力
            tmplate.merge(context, writer);
        } catch (Exception e) {
            System.out.println(e);
        }
        
        System.out.println("■結果を出力");
        System.out.print(writer.toString());
    }
}


MessageBucket.java
public class MessageBucket {
    private String name;
    private int salary;
    private int expense;
    
    public MessageBucket(String name, int salary, int expense) {
        this.name = name;
        this.salary = salary;
        this.expense = expense;
    }
    
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getSalary() {
        return salary;
    }

    public void setExpenses(int expense) {
        this.expense = expense;
    }

    public int getExpense() {
        return expense;
    }
}

出力結果

■結果を出力
「わんわんお」さんのお金使用状況

今月のお給料 : 100円
今月のお出費 : 1000円

ひゃっはー金がないぜ!

VTLについて

VTLとは、Velocityで使うテンプレートファイルで使用する言語です。
制御構文やループなどができますので、基本的なサンプルを以下に示します。

テンプレートファイル

## こうするとコメント文になります
#*
        こうすると囲まれた範囲がコメントとなります
        変数を出力する際、「$クラスのプロパティ名」としていますが、「${クラスのプロパティ名}」
        という表記ができます。
        これはaaaという文の前にaaaというプロパティを記述したい場合「$aaaaaa」となってしまい、判別不能です。
        なので、「${aaa}aaa」と表記することで正しく動かすことができます。
*#

-----------------------------------
$pageInfo.pageTitle             ($pageInfo.date)

「$dataBucket.msgBucket.name」さん
今年の収入 : $dataBucket.msgBucket.salary
今年の出費 : $dataBucket.msgBucket.expense
## 以下のように繰り返しも可能です
## $velocityCountという値がループ中のカウンタ名です(Velocityのデフォルト設定)
## $objはjavaの拡張forループみたいに、ループ内で使用する変数名です
詳細:
#foreach($obj in $dataBucket.msgList) 
    <$velocityCount>
        $obj.name:
            収入 : $obj.salary
            出費 : $obj.expense
#end

## メソッドの引数を指定して呼び出しも可能です

給料に対する感想 : $dataBucket.evaluateSalary(0)
給料に対する感想 : $dataBucket.evaluateSalary(1)
給料に対する感想 : $dataBucket.evaluateSalary(100)
給料に対する感想 : $dataBucket.evaluateSalary(500)
給料に対する感想 : $dataBucket.evaluateSalary(1000)
給料に対する感想 : $dataBucket.evaluateSalary($dataBucket.msgBucket.salary)
-----------------------------------

Javaのソース

VelocitySample.java mainからnew VelocitySample().doWork2()って呼べば動くよ!
import java.io.StringWriter;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

/**
 * apache Velocityを使用するに当たり以下のjarが必要
 *
 * Avalon-logkit-2.1.jar
 * Commons-collections-3.2.1.jar
 * Commons-lang-2.4.jar
 * Oro-2.0.8.jar
 * Velocity-1.7.jar
 */
public class VelocitySample {
    
    /** テンプレートファイルがあるディレクトリのパス */
    private static String TEMPLATE_FILE_DIRECTORY = "D:/dev/jdev/default/mywork/JavaProgram/template";
    
    /**
     * VTLの制御構文など
     */
    public void doWork2() {
        StringWriter writer = new StringWriter();
        
        // データを用意する
        DataBucket bucket = new DataBucket();
        List<MessageBucket> list = new LinkedList<MessageBucket>();
        list.add(new MessageBucket("1月",  100, 100));
        list.add(new MessageBucket("2月",  200, 1000));
        list.add(new MessageBucket("3月",  300, 10000));
        list.add(new MessageBucket("4月",  400, 10));
        list.add(new MessageBucket("5月",  500, 100));
        list.add(new MessageBucket("6月",  600, 1000));
        list.add(new MessageBucket("7月",  700, 10000));
        list.add(new MessageBucket("8月",  800, 100000));
        list.add(new MessageBucket("9月",  900, 1000000));
        list.add(new MessageBucket("10月", 100, 10000000));
        list.add(new MessageBucket("11月", 200, 100000000));
        list.add(new MessageBucket("12月", 300, 1000000000));
        
        // 1年の給料と出費を計算
        int salary = 0;
        int expense = 0;
        for(MessageBucket msgBucket : list) {
            salary += msgBucket.getSalary();
            expense += msgBucket.getExpense();
        }
        bucket.setMsgBucket(new MessageBucket("わんわんお", salary, expense));
        bucket.setMsgList(list);
        
        PageInfo pageInfo = new PageInfo();
        pageInfo.setDate(new Date());
        pageInfo.setPageTitle("サンプルページですよ☆ミ");
        
        
        try {
            Velocity.setProperty("file.resource.loader.path", TEMPLATE_FILE_DIRECTORY);
            
            Velocity.init();
            VelocityContext context = new VelocityContext();
            context.put("pageInfo", pageInfo);
            context.put("dataBucket", bucket);
            
            Template tmplate = Velocity.getTemplate("sample2.vm", "MS932");
            tmplate.merge(context, writer);
        } catch (Exception e) {
            System.out.println(e);
        }
        
        System.out.println("■結果を出力");
        System.out.print(writer.toString());
    }
}


DataBucket.java
import java.util.List;

public class DataBucket {
    
    private List<MessageBucket> msgList;
    private MessageBucket msgBucket;
    
    /** 挨拶メッセージを返すメソッド */
    public String getGreeting() {
        return "ゆがみねぇな(挨拶)";
    }
    
    /** もらってる給料により、感想を返します */
    public String evaluateSalary(int salary) {
        if (salary < 1) {
            return "へいどうぞ!";
        } else if (salary < 500) {
            return "最後は仕方ない";
        } else if (salary < 700) {
            return "芋が無いと失礼だ";
        }else if (salary < 5000) {
            return "超スピード!!!!!!";
        } else {
            return "仕方ないね";
        }
    }

    public void setMsgList(List<MessageBucket> msgList) {
        this.msgList = msgList;
    }

    public List<MessageBucket> getMsgList() {
        return msgList;
    }

    public void setMsgBucket(MessageBucket msgBucket) {
        this.msgBucket = msgBucket;
    }

    public MessageBucket getMsgBucket() {
        return msgBucket;
    }
}


MessageBucket.java
public class MessageBucket {
    private String name;
    private int salary;
    private int expense;
    
    public MessageBucket(String name, int salary, int expense) {
        this.name = name;
        this.salary = salary;
        this.expense = expense;
    }
    
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getSalary() {
        return salary;
    }

    public void setExpenses(int expense) {
        this.expense = expense;
    }

    public int getExpense() {
        return expense;
    }
}


PageInfo.java
import java.util.Date;

public class PageInfo {
    private String pageTitle;
    private Date date;
    
    public void setPageTitle(String pageTitle) {
        this.pageTitle = pageTitle;
    }

    public String getPageTitle() {
        return pageTitle;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Date getDate() {
        return date;
    }
}

実行結果

■結果を出力


-----------------------------------
サンプルページですよ☆ミ             (Fri Nov 04 01:15:43 JST 2011)

「わんわんお」さん
今年の収入 : 5100
今年の出費 : 1111122210
詳細:
    <1>
        1月:
            収入 : 100
            出費 : 100
    <2>
        2月:
            収入 : 200
            出費 : 1000
    <3>
        3月:
            収入 : 300
            出費 : 10000
    <4>
        4月:
            収入 : 400
            出費 : 10
    <5>
        5月:
            収入 : 500
            出費 : 100
    <6>
        6月:
            収入 : 600
            出費 : 1000
    <7>
        7月:
            収入 : 700
            出費 : 10000
    <8>
        8月:
            収入 : 800
            出費 : 100000
    <9>
        9月:
            収入 : 900
            出費 : 1000000
    <10>
        10月:
            収入 : 100
            出費 : 10000000
    <11>
        11月:
            収入 : 200
            出費 : 100000000
    <12>
        12月:
            収入 : 300
            出費 : 1000000000


給料に対する感想 : へいどうぞ!
給料に対する感想 : 最後は仕方ない
給料に対する感想 : 最後は仕方ない
給料に対する感想 : 芋が無いと失礼だ
給料に対する感想 : 超スピード!!!!!!
給料に対する感想 : 仕方ないね
-----------------------------------