夏休み前の小ネタです。
JavaでViewを書く時って、最近は何を使うのが流行りなのでしょうか?いろいろあると思いますが、まだまだVelocityやFreeMarkerといったテンプレートエンジンが主流だよという開発現場も多いと思います。
…自分のことです。
Apache Velocity
http://velocity.apache.org/
FreeMarker
http://freemarker.org/
で、これらを使うはいいんですけど、初めて使う時とか、ちょっと構文やディレクティブを確認したい時に、Groovyだと簡単に試せるよ!というお話。
Velocityだと拡張子が「.vm」、FreeMarkerだと拡張子が「.ftl」のファイルを通常テンプレートとして作成して、テンプレートの評価を行います。
が、わざわざファイルを用意しなくても、Stringをテンプレートとするクラスが、両ライブラリには備わっています。
StringResourceLoader
http://velocity.apache.org/engine/releases/velocity-1.7/apidocs/org/apache/velocity/runtime/resource/loader/StringResourceLoader.html
StringTemplateLoader
http://freemarker.org/docs/api/freemarker/cache/StringTemplateLoader.html
なんですが、テンプレートって1行で済むものじゃないし、Javaだと複数行に跨る文字列を書くの、面倒ですよね。
その他、クラスパスの設定をして…Mavenでもいいですよ?でも、最初に動かすまで、いろいろ準備が大変ですよね。
そこで、オススメしたいのがGroovy+Grapeを使うことです。
ライブラリの依存関係は、Grapeで一発!
Velocity
@Grab('org.apache.velocity:velocity:1.7')
@Grab('org.freemarker:freemarker:2.3.20')
複数行に跨るテンプレートを書くのも、Groovyなら簡単です。
Velocity
// テンプレートの内容 def templateAsString = '''\ Hello ${name}!! このブログのURLは、${blog_url}です。 プログラミング言語: #foreach ($language in $languages) ${language} #end Mapでバインド: key1 => ${map.key1} key2 => ${map.key2} Groovy参考書籍: タイトル:${book.title} お値段:${book.price} 発売日:${book.publishDate}'''
// テンプレートの内容 def templateAsString = '''\ Hello ${name}!! このブログのURLは、${blog_url}です。 プログラミング言語: <#list languages as language> ${language} </#list> Mapでバインド: key1 => ${map.key1} key2 => ${map.key2} Groovy参考書籍: タイトル:${book.title} お値段:${book.price} 発売日:${book.publishDate}'''
複数行に跨る文字列を「'''」で囲っているところが、Groovy的にはポイントです。
では、それぞれちょっとしたサンプルを。
Velocity
velocity-runner.groovy @Grab('org.apache.velocity:velocity:1.7') import org.apache.velocity.VelocityContext import org.apache.velocity.Template import org.apache.velocity.app.Velocity import org.apache.velocity.runtime.resource.loader.StringResourceLoader // テンプレート名 def templateName = 'stringTemplate.vm' // テンプレートの内容 def templateAsString = '''\ Hello ${name}!! このブログのURLは、${blog_url}です。 プログラミング言語: #foreach ($language in $languages) ${language} #end Mapでバインド: key1 => ${map.key1} key2 => ${map.key2} Groovy参考書籍: タイトル:${book.title} お値段:${book.price} 発売日:${book.publishDate}''' // StringResourceLoaderを使用するように設定 Velocity.addProperty(Velocity.RESOURCE_LOADER, 'string') Velocity.addProperty('string.resource.loader.class', StringResourceLoader.class.name) // Velocityの初期化 Velocity.init() // テンプレートの登録 def repository = StringResourceLoader.repository repository.putStringResource(templateName, templateAsString) def template = Velocity.getTemplate(templateName, 'UTF-8') // VelocityContextの作成 def context = new VelocityContext() // テンプレートにバインドするデータを登録 context.put('name', 'Velocity') context.put('blog_url', 'http://d.hatena.ne.jp/Kazuhira/') context.put('languages', ['Java', 'Groovy', 'JavaScript', 'Perl', 'PHP']) context.put('map', [key1: 'value1', key2: 'value2']) context.put('book', new Book(title: 'プログラミングGROOVY', price: 3360, publishDate: '2011/07/06')) // テンプレートの評価と結果表示 def writer = new StringWriter() template.merge(context, writer) println(writer.toString()) class Book { def title def price def publishDate }
FreeMarker
freemarker-runner.groovy
@Grab('org.freemarker:freemarker:2.3.20') import freemarker.cache.StringTemplateLoader import freemarker.template.Configuration // テンプレート名 def templateName = 'stringTemplate.ftl' // テンプレートの内容 def templateAsString = '''\ Hello ${name}!! このブログのURLは、${blog_url}です。 プログラミング言語: <#list languages as language> ${language} </#list> Mapでバインド: key1 => ${map.key1} key2 => ${map.key2} Groovy参考書籍: タイトル:${book.title} お値段:${book.price} 発売日:${book.publishDate}''' def configuration = new Configuration() // NumberFormatは変えてます… configuration.numberFormat = '###' // 該当のテンプレートに対して、StringTemplateLoaderを使用するように設定 def templateLoader = new StringTemplateLoader() templateLoader.putTemplate(templateName, templateAsString) configuration.templateLoader = templateLoader def template = configuration.getTemplate(templateName) // テンプレートにバインドするデータを登録 def context = [:] context.put('name', 'FreeMarker') context.put('blog_url', 'http://d.hatena.ne.jp/Kazuhira/') context.put('languages', ['Java', 'Groovy', 'JavaScript', 'Perl', 'PHP']) context.put('map', [key1: 'value1', key2: 'value2']) context.put('book', new Book(title: 'プログラミングGROOVY', price: 3360, publishDate: '2011/07/06')) // テンプレートの評価と結果表示 def writer = new StringWriter() template.process(context, writer) println(writer.toString()) class Book { def title def price def publishDate }
実行結果は、それぞれこんな感じです。
Velocity
$ groovy velocity-runner.groovy Hello Velocity!! このブログのURLは、http://d.hatena.ne.jp/Kazuhira/です。 プログラミング言語: Java Groovy JavaScript Perl PHP Mapでバインド: key1 => value1 key2 => value2 Groovy参考書籍: タイトル:プログラミングGROOVY お値段:3360 発売日:2011/07/06
$ groovy freemarker-runner.groovy Hello FreeMarker!! このブログのURLは、http://d.hatena.ne.jp/Kazuhira/です。 プログラミング言語: Java Groovy JavaScript Perl PHP Mapでバインド: key1 => value1 key2 => value2 Groovy参考書籍: タイトル:プログラミングGROOVY お値段:3360 発売日:2011/07/06
とまあ、いろいろ用意しなくても比較的簡単に動かすことができます。
Groovyの文法を覚えていない場合は?この例は、Groovyの構文をそれなりに出していますが、Javaのほぼ上位互換でもあるので、慣れないならJavaの構文で書いてもだいたいは大丈夫です。
Velocity、FreeMarkerに限らず、簡単な動作確認とかはサクッと行えるので、Java開発にどっぷりな現場ほど、Groovyを使うと便利な局面がそれなりにあるんじゃないかなーと思います。
簡単なスクリプトを書いたり、GroovyConsoleも便利ですよ。
…と、ちょっと変わったノリでエントリを書いてみました。