Velocity空间

快速构建JAVA应用
随笔 - 11, 文章 - 15, 评论 - 5, 引用 - 0
数据加载中……

CHAPTER 5 构建Hello World示例

 

目前,你已经对Velocity有了一个很好的理解,并且理解了MVC是如何工作的,同时也搭建一个Velocity的工作环境,是时候开始学习如何Velocity了。正如你所期望的一样,第一个示例就是Hello World

Hello World!

首先,你需要确定HTML页面的Hello World模板和在页面上显示些什么信息。如果我们仅仅简单的输出“Hello World”,这就不能很好体现Velocity的特性。因此,我们准备生成一个模板,输出内容为:“Hello World, Sam is Here”,在这里,“Sam”用的是引用值。

现在,你已经知道了页面需要输出的内容,接下来,你需要和JAVA开发者一起讨论并确定页面所需要引用对象的名称(此处的引用对象是“Sam”),在这里我们将这个引用对象的名称约定为“name”。在构建Hello World示例时,你需要考虑以下三个版本:

不使用上下文的Velocity模板

使用上下文的Velocity模板

使用WEBVelocity模板

如果你已经非常熟悉服务器端语言,比如PHP,你或许会非常惊奇,在Velocity模板被浏览时,我们为什么不讨论WEB服务器的解释程序。这是因为Velocity并不含解释程序,它是纯JAVA语言,属性编译运行方式,而非解释运行方式。所有在模板和上下文之间的合并处理都是通过JAVA代码来完成的。这些JAVA代码可能存在于Servlet中,也可嵌入JSP或应用程序中。

WEB中使用Velocity时,很多情况下是使用Servlet来处理模板转换工作的。

不使用上下文的Velocity模板

Hello World示例代码见Listing 5.1,它使用Velocity指令语句#set来为模板中引用指定一个值(在模板中使用),同时使用嵌入Hello World文本的$name指令来引用#set指定的值。

这个示例比较容易理解,在Velocity对模板进行解析时,如果是普通的文本,则忽略,直接输出;当遇到#set指令时,它就创建一个名叫$name的内部变量(在模板文件中指定的),并赋值为"Sam"(在模板文件中指定的);接着,程序将直接输出“Hello World”文本;在系统处理到$name引用时,系统将尝试在上下文中查找一个名叫$name的对象,如果在上下文中没有匹配的对象,系统将尝试匹配之前用#set创建的引用。

#set( $name = "Sam" )

Hello World, $name is Here

Listing 5.1 The Velocity Hello World template.

当然,仅仅拥有一个模板是不能工作的,你还需要一个把模板和上下文合并,并输出给用户的途径。Listing 5.2显示了一个独立应用需要用到的相关代码。

import org.apache.velocity.app.Velocity;

import org.apache.velocity.VelocityContext;

import org.apache.velocity.Template;

import org.apache.velocity.exception.ParseErrorException;

import org.apache.velocity.exception.ResourceNotFoundException;

import java.io.*;

import java.util.ArrayList;

public class Example {

//从命令行参数获取模板文件,并进行初始化操作

public Example(String templateFile) {

try {

Velocity.init();

VelocityContext context = new VelocityContext();

Template template = null;

try {

template = Velocity.getTemplate(templateFile);

} catch(ResourceNotFoundException e2 ) {

System.out.println(

"cannot find template " + templateFile );

} catch(ParseErrorException e ) {

System.out.println(

"Syntax error in template : " + e);

}

BufferedWriter writer = new BufferedWriter(

new OutputStreamWriter(System.out));

if ( template != null)

template.merge(context, writer);

writer.flush();

writer.close();

} catch( Exception e ) {

System.out.println(e);

}

}

public static void main(String[] args) {

Example t = new Example(args[0]);

}

}

Listing 5.2 The Velocity application without context. (continued)

和许多的JAVA应用程序一样,这个示例需要导入一些JAVA包,前面5个导入了运行Velocity需要的类。当第一次运行这个示例时,需要在命令行提供模板文件名这个参数。如:

java Example example.vm

回头查看Listing 5.2的模板示例我们可以看到,模板文件的名称被放置到命令行上,并传递给新创建的示例对象。在这里,首先需要完成Velocity引擎的初始化操作,示例利用一个独立模式关联应用程序和Velocity引擎,这就意味着仅有一个静态引擎是可用的。记住这个事实很重要,因为你肯定不希望再看到示例中还有其他任何初始化引擎的代码。

一旦引擎被初始化,就将从本地磁盘上加载模板。模板是通过Velocity引擎对象的getTemplate(String)方法进行加载的,该方法的结果是调用了一个模板对象;另外,如果没有找到,就会抛出异常。很重要的一点是,当找不到模板文件或把模板文件解析成模板对象出错时,异常将通过ResourceNotFoundException进行抛出。当读取模板并进行解析时出错,也会抛出ParseErrorException异常。

当模板被读入到系统之后,你就可以开始处理输出了。此处要注意的是,除了输出到控制台的方式外,还可以输出为一个文件、一个套接字socket或其他的输出。

在这个示例里,你已经在应用程序里使用了几个不同的内容:

Velocity一个静态对象,表现为Velocity引擎

Context一个上下文对象

Template一个模板对象,在从本地磁盘读入Velocity模板文件时创建

Writer一个BufferedWriter对象,用于向控制台直接输出(通过System.out流)。在输出前,要核实BufferedWriter已经正确进行了初始化。之后,Velocity引擎通过使用模板对象的merge()方法(带有两参数:一个上下文对象和一个BufferedWriter对象)来完成内容合并。merge()方法带有两参数:一个上下文对象和一个BufferedWriter对象,当模板对象执行merge()方法时,上下文被合并到模板文件中,同时用上下文中对应的值替换模板中的脚本元素,完成输出创建工作。

最后,冲洗(flush)和关闭输出流。Figure 5.1 显示了输出结果。


Figure 5.1
Output from the Hello World example.

在这个示例里,我们将Listing 5.1中的模板内容保存为一个文件,命名为helloworld.vm。在这里,扩展名不限于VM,也可以是其他的扩展名,目的是与其他文件进行区别,比如:HTMLJSP,当然,也完全可以是定义的,比如XX。另外,我们把Listing 5.2的内容保存到一个名叫Example.java的文件中,并将其编译成class文件。

javac Example.java

执行示例的命令为

java Example helloworld.vm

如果Velocity引擎不能定位模板文件位置,将产生一个错误。

使用上下文的Velocity模板

在上一个示例里,我们通过#set指令来给$name引用指定值。但这样做将限制Velocity的动态处理能力,比如,如果需要动态的更改用户名称,就成为一个不可能完成的任务。要想获得这个能力,需要使用上下文对象,在第二个示例里,我们使用和Listing 5.1相同的模板,但删除了#set指令这一行,只保留现在这一行:

Hello World, $name is Here

JAVA代码中找到下面这行代码

VelocityContext context = new VelocityContext();

在其之后加上下面这行代码:

context.put("name", "New Sam");

存储这个文件,编译和执行它。你就将看到这样的输出“Hello World, New Sam is Here.”。现在让我们试一试其他,打开这个应用程序代码,改变context.put的参数内容。

context.put("names", "New Sam");

重新编辑并执行。输出结果为“Hello World, $name is here”,为什么会得到这个输出?好,让我们再仔细看一下context.put()语句。正如你在前面章节学到的一样,Velocity像变魔法一样把模板和上下文合并到一起,所有在模板的引用,比如$name必须和上下文对象中的关键字相匹配。因此,Velocity将尝试在上下文对象中查找关键字“name”来与模板引用$name相匹配。如果匹配上了,则将上下文中关键字“name”中保存的值“New Sam”合并入模板并返回给用户;如果在上下文中没有找到对应的关键字,引擎将直接把“$name”作为字符串返回,不进行任何合并操作。

在这里,之所有输出为“Hello World, $name is here”,是因为我们把context.put()的关键字改成了“names”,也就是说在上下文中保存的是“names”关键字的值,Velocity引擎也就不能匹配模板的$name引用,所以Velocity引擎直接返回$name字符串。

使用WEBVelocity模板

迄今为此,我们所做的两个示例都是用于独立的JAVA应用程序。然而,当把Velocity用于替代jSP时,你可能最期待的就是把Velocity用于WEB应用程序。在这一节里,我们将看一看如何在Servlets里使用Velocity。关于这个主题的更多信息,详见Chapter 12“在Servlets里使用Velocity”,Listing 5.3展示了一个用于在浏览器里显示一个XML文档的新模板。正如你所看到的一样,这个模板有一些小的功能。

在之后的章节里,我们将检验更多的模板语句。目前,你首先需要关注的第一个在#foreach#next指令之间的语句。这些指令允许你创建一个基于某些引用(此处为$value)的循环。

<?xml version="1.0" encoding="ISO-8859-1" ?>

<list>

#foreach( $value in $list )

<number>$value</number>

#end

</list>

Listing 5.3 The servlet example template.

Listing 5.4 向你展示了用于产生XMLservlet代码。正如我们说及的一样,我们将在Chapter 12详细讨论Servlets,这里我们只关注Velocity对象的创建和三个增加到里面的值。用context.put("list", v)语句把整个Vector对象附属到上下文中。

import java.util.Vector;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.Template;

import org.apache.velocity.context.Context;

import org.apache.velocity.servlet.VelocityServlet;

import org.apache.velocity.exception.ResourceNotFoundException;

import org.apache.velocity.exception.ParseErrorException;

public class VelocityServletExample extends VelocityServlet {

public Template handleRequest( HttpServletRequest request,

HttpServletResponse response,

Context context ) {

Vector v = new Vector();

v.add("one");

v.add("two");

v.add("three");

context.put("list", v);

Template template = null;

try {

template = getTemplate("displaylist.vm");

} catch( Exception e ) {

System.out.println("Error " + e);

}

return template;

}

}

Listing 5.4 The servlet code for our example.

一旦vector被放置到上下文对象中,就需要从本地磁盘上获取用于显示上下文信息的模板。现在不再使用模板对象的merge()方法进行合并操作,而是简单的返回模板。这个模板实际上不会直接返回给用户,而是在后台对“被返回来的”模板和上下文进行合并处理,并返回给用户一个XML的类型的内容。在Figure 5.2里,你可以看到由Servlets和模板创建的XML输出。如果需要,你也可以使用Velocity向用户的浏览器输出HTML


Figure 5.2
The servlet and template example output.

本章小节和下章介绍

在这一章里,我们向你展示了如何用Velocity来书写Hello World独立应用程序。你可以使用Velocity来开发独立应用程序和WEB应用。在下一章里,我们将开始详细介绍Velocity,并学习它与其他语言不一样的特性。

posted on 2008-10-13 00:42 KINGWEE 阅读(695) 评论(0)  编辑  收藏 所属分类: Velocity


只有注册用户登录后才能发表评论。


网站导航: