JRuby Velocity

2007年1月19日

昨天我需要使用 Velocity 来探索一些关于模板和宏的东西。我喜欢 Velocity 的简单模板语言,但这次我并没有在 Java 或 .NET 工作中使用它。在这种情况下,使用 Velocity 会有点麻烦,因为你必须在 Java 中设置上下文并运行处理器。

这种情况需要一种脚本语言,我首选的脚本语言是 Ruby,因此我认为这是一个尝试 JRuby 的好机会。我的结论是它运行得很好,但我不会让你厌烦细节。

我下载了 JRuby 并将其解压缩到 /usr/local/lib 中,并创建了一个符号链接,以便我可以通过 /usr/local/lib/jruby 访问它。

然后,我在 /usr/local/bin 中放置了一个简单的重定向 shell。

JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun
JRUBY_HOME=/usr/local/lib/jruby

/usr/local/lib/jruby/bin/jruby "$@"

然后我就可以运行 JRuby 了。

$ jruby -v
ruby 1.8.5 (0) [java]

(实际上,我花了很长时间才让它工作,最终我在椅子和键盘之间找到了错误。我太尴尬了,不想告诉你是什么。)

要运行 Velocity,你必须将其添加到 JRuby 的类路径中。

CLASSPATH=path/to/velocity-dep-1.4.jar
export CLASSPATH
jruby "$@"

为了帮助运行 Velocity,我编写了一个小助手类。

require 'java'

class VelocityLauncher
  def initialize context, template
    @context = context
    @template = template
  end

  include_class 'org.apache.velocity.app.Velocity'
  include_class 'org.apache.velocity.VelocityContext'
  include_class 'java.io.StringWriter'

  def run
    vc = VelocityContext.new(@context)
    writer = StringWriter.new
    Velocity.init
    Velocity.evaluate(vc, writer, "LOG", @template)
    return writer.getBuffer
  end
end

现在我可以编写一个小的模板

This is an announcement from $host

Our chief weapons are:
#foreach ($w in $weapons) 
  - $w 
#end

要填充它,我只需要一个 Ruby 哈希,这很容易创建。

ct = {'host' => 'Cardinal Fang', 
  'weapons' => ['Fear', 'Surprise', 'Ruthless Efficiency']}
template = File.readlines('template.txt').join

puts VelocityLauncher.new(ct, template).run

我可以想象将它扩展为一个不错的 Velocity 命令行运行器,它将接受以下形式的上下文文件:

host = 'Cardinal Fang'
weapons = ['Fear', 'Surprise', 'Ruthless Efficiency']

但我现在还不需要它,所以我会在另一天完成它(而且我很确定“另一天”的绑定是什么)。