以标准表示或交换格式(例如HTML和XML)操作和转换文本数据是每个软件开发人员都参与的频繁且通常乏味的活动。 模板引擎可以通过在模板中维护输出的静态部分,同时动态生成和定位变化部分来促进此过程。 Velocity是一种功能强大的开源模板引擎,您可以轻松地将其集成到客户端或服务器端应用程序中。
对于服务器端应用程序,当与兼容Servlet 2.3+的Web层容器集成在一起时,Velocity提供了JSP技术的可行替代方案,可以强制将表示逻辑与应用程序业务逻辑完全分开。 实际上,Velocity支持的模板语言非常简单,并且生成的模板足够整洁,以使网站设计者和设计师可以学习和维护这些模板。
在本文中,我们将研究Velocity的简单模板语言,创建一些模板,并将其应用于独立的客户端应用程序中。 然后,我们将模板引擎作为视图组件集成到Struts MVC框架中。
基本模板引擎操作
基本模板引擎的操作非常简单。 首先考虑清单1中的模板:
清单1.基本的Velocity模板
<html>
<head>
<title>A Template Based Page</title>
</head>
<body>
<p>This is a page generated by $generatedBy.</p>
<p>The customer's name is $customerName.</p>
</body>
</html>
该模板是完整HTML文件。 您可以使用文本编辑器或收藏的图形可视网页编辑器来创建它。 这种易于创建的功能是基于模板的系统的主要优点和吸引力。
当模板引擎运行时,清单1模板中的粗线将被实际数据替换。 获取数据并将其组合成模板的过程称为合并 。 考虑清单2中脚本中表示的数据:
清单2.设置模板合并的数据值
#set ($generatedBy = "Velocity")
#set ($customerName = "John Doe")
现在,如果清单1模板与清单2数据合并,结果将如清单3所示:
清单3.与模板合并的数据
<html>
<head>
<title>A Template Based Page</title>
</head>
<body>
<p>This is a page generated by Velocity.</p>
<p>The customer's name is John Doe.</p>
</body>
</html>
您可能会认识到此功能与文字处理器中的邮件合并功能相似,在文字处理器中,将套用信函与邮件列表中的名称和地址进行合并。 与邮件合并一样,当要合并的数据源很大且种类繁多时,该应用程序最有用。
从纯粹的意义上讲,速度是一个模板引擎。 Velocity的输出格式仅受文本模板中可以放置的内容的限制。 其中包括当今最流行的格式(HTML,XML,SQL等)。
使用Velocity模板语言创建模板
速度模板是文本文件(HTML,XML等),包含:
- 将原样合并的静态部分
- 将被合并数据替换的占位符
- 脚本语言中的指令和说明
与Velocity模板一起使用的脚本语言称为Velocity模板语言(VTL)。 与其他脚本语言相比,VTL语法相对较精简。 对于具有编程背景的任何人来说,学习VTL应该是一项快速的任务。
占位符和参考
VTL中的引用是一个命名元素,例如$customerName
。 引用可以充当Velocity模板中的数据占位符。 在模板合并以创建最终输出时,这些占位符将替换为其文本值。 例如,回到清单1 ,我们可以看到用于创建最终输出的两个VTL引用( $generatedBy
和$customerName
)。 变量是VTL中的一种引用类型。 您可以使用#set()
指令为变量分配值。 清单4显示了一些示例:
清单4.变量类型的VTL引用
#set( $this = "Velocity")
#set( $numericBase = 999 )
#set( $booleanCondition = true )
This page is generated using $this.
There are ($numericBase + 1) pages in total.
变量名必须以字母开头,这使得Velocity可以轻松地将变量名与模板中的货币表示法区分开(例如, $100
不能是变量名)。 在合并操作期间,所有变量都将转换为字符串,这可能会产生一些有趣的情况。 考虑清单4中以红色突出显示的文本。清单5显示了合并后的输出:
清单5.合并模板中具有数值的变量
This page is generated using Velocity.
There are (999 + 1) pages in total.
因为$numericBase
在合并操作期间转换为字符串,所以不执行算术运算。 因为VTL专用于模板操作,而不是通用的计算语言,所以VTL只需要支持整数数学(尽管可以使用插件工具来扩展它)。 下面的脚本展示了如何使用此数学功能:
#set( $newSum = $numericBase + 1)
There are $newSum pages in total.
合并此模板后,相应的输出将是:
There are 1000 pages in total.
到目前为止,我们只处理了标量变量。 要创建由多个元素组成的ArrayList
变量,请使用以下语法: #set( $treeList = ["pine", "oak", "maple", "redwood"])
您可以使用$treeList.get(1)
获得列表中的第二项。
赋值后, $treeList
是一个基于ArrayList
的变量(与标准JDK集合类相同)。 您可以使用$treeList.get(n)
表示法直接访问其每个元素,其中n
是从零开始的索引ArrayList
。 例如,如清单6中红色突出显示的行所示 , $treeList.get(1)
用于选择ArrayList
:Oak中的第二项。 调用ArrayList
类的方法的语法可用于调用其他可用对象的方法(有关更多信息,请参见“ 属性和方法引用”侧边栏)。
现在,关于占位符替换的一句话是:Velocity将所有无法识别的参考打印为纯文本,如清单6中接下来的两个粗体所示:
清单6.占位符替换
The second item in the list is $treeList.get(1).
$notDeclared is an undeclared variable.
But $!notDeclared is invisible when not declared.
VTL支持静默引用表示法,以避免呈现不存在或为null
引用。 如果您使用$!notDeclared
的安静引用表示法,则Velocity将不输出任何内容,而不是完整引用名。 注意“!” 在变量名之前表示静默引用符号。 合并清单6模板时,两个引用均未分配任何值,但是第一个粗体引用将按原样呈现,而第二个粗体引用将不可见:
The second item in the list is oak.
$notDeclared is an undeclared variable.
But is invisible when not declared.
选择性渲染和重复
您可以使用#if... #then... #else....
指令有条件地呈现模板的特定部分。 清单7显示了一个示例:
清单7.使用#if,#then和#else进行选择性渲染
#if $customer.GoldMember
Thank you Mr. $customer.LastName, for flying with us.
Your loyal patronage is greatly appreciated.
This flight earns you an additional 5000 miles.
#else
Thank you for flying with us.
Please consider joining our frequent flyer program.
#endif
在清单7模板中, $customer
对象的boolean GoldMember
属性用于确定要在最终输出中显示的消息。 对于金牌会员,将显示第一个粗体消息; 否则,第二个粗体消息将显示在最终输出中。
模板中经常需要重复,以表格或列表格式设置信息格式。 显示的数据通常保存在ArrayList
引用中。 用于处理Velocity中重复循环的唯一指令是#foreach
指令。 清单8模板说明了将#foreach
指令与$treeList ArrayList
变量一起使用。 当然,也可以使用任何其他可用的集合类型的对象引用,或者返回集合的对象属性/方法引用。
清单8.使用#foreach进行重复
<table>
<tr><td>Tree Name</td></tr>
#foreach $name in $treeList
<tr><td>
$name is a big tree!
</td></tr>
#end
</table>
在$treeList
包含树名列表的情况下,清单8模板的合并输出将类似于清单9:
清单9. #foreach循环的合并输出
<table>
<tr><td>Tree Name</td></tr>
<tr><td>
pine is a big tree!
</td></tr>
<tr><td>
oak is a big tree!
</td></tr>
<tr><td>
maple is a big tree!
</td></tr>
<tr><td>
redwood is a big tree!
</td></tr>
</table>
从HTML浏览器查看时,清单9当然是一个树名表。
请注意,在#foreach
循环的主体内部有一个“内置”计数器。 可通过#foreach
指令正文中的$velocityCounter
引用进行访问。 默认情况下,该计数器从1开始,并在每次循环时递增。
速度宏
Velocity的一个主要特征是它能够轻松定义称为Velocimacros的宏。 宏使您可以封装模板脚本并轻松地重用它们。 默认情况下,它们保存在VM_global_library.vm
文件中。 例如,考虑清单10中称为#showTree()
:
清单10.定义Velocimacro
#macro (showTree)
#if ($treeList )
#foreach ($e in $treeList )
$e
#end
#end
#end
您可以调用#showTree()
并使用它来打印$treeList
ArrayList(前提是已定义列表)。 调用语法只是#showTree()
。
您也可以参数化宏。 例如,我们可以修改#showTree()
宏以使其适用于任何列表,如清单11所示:
清单11.一个带有参数的Velocimacro
#macro (showList $val)
#if ($val )
#foreach ($e in $val )
$e
#end
#end
#end
要使用$treeList
调用清单11宏,我们可以使用#showList($treeList)
。 两种情况下的输出都是相同的,如清单12所示:
清单12. Velocimacro的合并输出
pine
oak
maple
redwood
其他有趣的VTL详细信息
单行注释或行末注释以##
。 多行注释由#*
和*#
对括起来。
处理字符串数据时,可以使用双引号或单引号来定界。 但是,使用双引号可以评估定界字符串内的Velocity引用,指令甚至Velocimacros。
速度上下文
您可以将Velocity中的上下文视为导入Java对象以在Velocity模板中进行访问的一种方式。 必须使用Java编码显式完成此导入。 与JSP代码或JavaScript不同,Velocity模板没有“自然”或“本机”方式访问任意Java对象。 在Velocity模板中,只有显式导入的Java对象才可用。
您可以通过创建org.apache.velocity.context.Context
类的实例来获取Velocity上下文。 然后,您可以使用上下文的put( key , value )
方法将要导入以供模板使用的对象附加到上下文。 关键字将是一个字符串名称,它将作为模板中的可用引用出现。 在生产方案中,图形或Web设计人员可能负责创建和维护模板,而Java开发人员则提供了可在模板内部访问的对象集。 在这些情况下,设计人员和开发人员将通过就对象集及其可用属性达成协议来进行协作。 Velocity上下文中的附加属性将是主要的接口机制。
访问模板中的上下文属性
查看独立解析器随附的示例代码(请参阅参考资料 )。 在\code\src
目录下查看。 例如,在我们的com.ibm.dvworks.velocity.VelocityParser
类中,我们创建了两个属性并将其添加到Velocity上下文中,如清单13所示:
清单13.在我们的VelocityParser类中创建一个Velocity实例
public static void main(String[] args) {
VelocityParser velInstance = new VelocityParser(args[0]);
velInstance.addToContext( "treeFarm",
new String [] { "redwood", "maple", "oak", "pine" });
velInstance.addToContext( "title", "A Tree Farm");
velInstance.addToContext( "date", new java.util.Date());
velInstance.addToContext("fmtr",
new org.apache.velocity.app.tools.VelocityFormatter(
velInstance.getCurrentContext()));
velInstance.processTemplate();
}
属性treeFarm
是树名的ArrayList
。 title
属性是一个标量字符串。 一旦附加到上下文并在合并操作期间传递,这些属性即可在Velocity模板中立即使用。 清单14中的模板使用了这两个属性。 您可以在\code\app\treectx.vm
找到它。
清单14.使用$ treeFarm上下文属性引用
<table>
<tr><td>$title</td></tr>
#foreach $name in $treeFarm
<tr><td>
$name is a big tree!
</td></tr>
#end
</table>
合并后,输出类似于清单15:
清单15.模板的合并输出
<table>
<tr><td>A Tree Farm</td></tr>
<tr><td>
redwood is a big tree!
</td></tr>
<tr><td>
maple is a big tree!
</td></tr>
<tr><td>
oak is a big tree!
</td></tr>
<tr><td>
pine is a big tree!
</td></tr>
</table>
注意,使用$treeFarm
上下文属性引用的语法与前面检查的$treeList
变量引用相同。
初始化模板引擎
检查VelocityParser
类的main()
方法清单(请参见清单13)。 VelocityParser
的构造函数创建解析器并加载模板,然后添加要由模板引擎使用的属性,最后调用processTemplate()
合并数据和模板。 我们将依次检查每种方法。
您可以在org.apache.velocity.app.Velocity
类中使用静态方法来初始化Velocity并加载模板文件。 使用的方法分别是init()
和getTemplate()
。 调用init()
方法发生在我们的VelocityParser
类的构造函数中,如清单16所示:
清单16.在我们的VelocityParser类的构造函数中初始化模板引擎
public VelocityParser(String templateFile) {
try {
Velocity.init("velocity.properties");
mainTemplate = Velocity.getTemplate(templateFile);
}
catch( Exception ex ) {
System.out.println("Error processing template file: " + templateFile );
}
}
在清单16中,对init()
的调用创建了Velocity引擎的单个实例。 如果您的应用程序需要创建和管理Velocity模板引擎的多个实例,请改用org.apache.velocity.app.VelocityEngine
类。
上下文链接
只需调用org.apache.velocity.VelocityContext
类的琐碎构造函数,即可创建立即可用的Velocity上下文。
速度上下文可以被链接 (一个包裹在另一个包裹中)。 当您要控制模板中某些对象引用的可见性或可用性时,这可能非常有用。
Velocity将在所有链接上下文的属性中搜索对象引用。 如果存在重复的名称,将使用最外面的属性,并且将无法访问具有相同名称的内部属性。
要链接Velocity上下文,要链接的上下文作为参数传递给新上下文的构造函数。 如清单17所示, VelocityParser
类中重载的addToContext()
方法说明了这一点:
清单17.使用addToContext()方法添加上下文属性或上下文链接
public void addToContext(String key, Object value) {
if (mainContext == null)
mainContext = new VelocityContext();
mainContext.put(key, value);
}
public void addToContext(VelocityContext chainCtx) {
mainContext = new VelocityContext(chainCtx);
}
在processTemplate()
方法中,调用模板的merge()
方法以将上下文信息与模板组合并生成输出流,如清单18所示:
清单18.在processTemplate()方法中合并模板
public void processTemplate() {
try {
BufferedWriter writer = writer = new BufferedWriter(
new OutputStreamWriter(System.out));
if ( mainTemplate != null)
mainTemplate.merge(mainContext, writer);
writer.flush();
writer.close();
}
catch( Exception ex ) {
ex.printStackTrace();
}
}
速度作为独立解析器
要编译示例独立解析器,请使用发行版\code\app
目录中的compile.bat
文件。 要尝试解析器,请使用process.bat
批处理文件,该文件包含:
set VEL_HOME=\jdk1.4\vel14rc1
java -classpath ..\classes;%VEL_HOME%\velocity-dep-1.4-rc1.jar
com.ibm.dvworks.velocity.VelocityParser %1 %2 %3
请注意,必须将compile.bat
和process.bat
的VEL_HOME
环境变量都设置为安装Velocity的目录。 Velocity分发包含两个不同的JAR文件: velocity-dep-???.jar
(其中???是发行号信息)和velocity-???.jar
。 velocity-dep-???.jar
文件包含所有外部依赖项(Jakarta common-collections,Avalon Logkit和ORO正则表达式库),可以立即使用。 如果您的类路径中已经有这些库中的一些,则可能要改用velocity-???.jar
文件。 如果这两种JAR合成都不能完全满足您的需求,则可以轻松地重新构建Velocity,使其成为您所需的方式。 Velocity发行版包含一个ant脚本,用于针对不同的应用场景构建七个不同的JAR配置。
为了提供愉悦的开箱即用体验,Velocity附带了一组默认配置属性,这些属性对于大多数应用程序都是合理且可以接受的。 这样一来,开发人员就无需在最初使用时便去修改复杂的配置选项,并允许他或她立即尝试使用模板引擎。
服务器上的速度与JSP技术
在服务器端,您可以使用Velocity处理模板并生成动态内容(HTML,XML等)。 这在目的上与JSP技术非常相似。 但是,JSP模型提供了对底层Servlet API和Java编程语言的无障碍访问。 实际上,为了避免访问这些本机功能,您将不得不在编码方面进行严格训练(仅使用EL,标签库等)。 本质上,这是一个开放的访问模型。
将此与“速度”进行对比。 作为一个完全独立的模板引擎和脚本解释器,Velocity具有一个完全封闭的模型。 必须明确启用对系统和/或Java编程语言特定的任何内容的访问。 默认情况下,在Velocity模板中无法访问Java编程语言的任何方面。 这种封闭的模型允许Velocity提供分离的模板表示层,与任何应用程序业务逻辑或数据管理代码完全隔离。
现在,通过将模板引擎集成到最新的Tomcat 5版本中,来了解服务器端Velocity的运行情况。
使用Tomcat 5部署Velocity
Velocity发行版带有org.apache.velocity.servletVelocityServlet
库类,您可以对其进行扩展以快速创建模板处理servlet。 在独立客户端应用程序上测试的任何模板都可以使用VelocityServlet
部署在服务器上。 将独立的Velocity模板移动到Web应用程序相对容易。 只需执行以下步骤:
- 从
org.apache.velocity.servlet.VelocityServlet
类派生Servlet类。 - 重写并实现
handleRequest()
方法之一。 - 在
handleRequest()
的实现中,添加要在模板中用作上下文属性的数据或工具(请参见Velocity边栏中的工具)。 - 在
handleRequest()
的实现中,从文件或资源(例如JAR文件)中获取模板并返回它。
在示例代码分发中, com.ibm.dvworks.velocity.VelTestServlet
是我们按照上述步骤创建的servlet。 您可以在webapps\vservlet\WEB-INF\src
目录下检查代码。 如果修改代码,请确保使用compile.bat批处理文件重新编译它。
部署描述符(web.xml文件)定义了servlet并将其映射到/vServlet
URL模式,如清单19所示:
清单19.用于基于Velocity的定制servlet的Tomcat部署描述符
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>vServlet</servlet-name>
<servlet-class>com.ibm.dvworks.velocity.VelTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>vServlet</servlet-name>
<url-pattern>/vServlet</url-pattern>
</servlet-mapping>
</web-app>
要加载和处理的模板位于webapps\vServlet
目录中。 在我们的例子中,它称为variables.vm
。 要进行测试,请确保将velocity-dep-???.jar
文件放置在webapps\vServlet\WEB-INF\lib
目录中,然后启动Tomcat 5并访问http://localhost:8080/vservlet/Servlet
URL。
部署VelocityViewServlet
对于Web应用程序的广泛模板的工作,你应该使用VelocityViewServlet
从速度工具的集合。 Velocity工具是Velocity的子项目(请参阅参考资料中的URL以下载最新版本)。 该Servlet为将Velocity用作视图层技术提供了更完整的支持,可以与JSP技术结合使用或代替JSP技术使用。 使用VelocityViewServlet
可以节省大量的冗余编码,因为它提供了:
- 直接模板访问请求对象和属性,会话对象和属性以及Servlet上下文和属性
- 一个形式化的,可在外部配置的“工具箱”,用于添加模板可以使用的自定义工具(在这种意义上,工具只是具有公共方法的已编译Java类)
- 多种功能,经过测试的即用型工具库
要将VelocityViewServlet
集成到您的Web应用程序中,请看一下示例velview Web应用程序(在webapps\velview
目录中)。 该应用程序包括本文中一直在使用的模板。 此外,它还显示来自请求,会话和Servlet上下文对象的属性。 集成步骤如下:
首先,请确保velocity-tools-view.jar
文件位于应用程序的lib
目录中。 当然,速度JAR文件也应位于此处。
在部署描述符web.xml文件中,包括VelocityViewServlet
。 初始化参数是工具箱描述XML文件。 该servlet被映射为处理所有扩展名为.vm的文件,如清单20所示:
清单20. VelocityViewServlet的Tomcat部署描述符(web.xml)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>velocityView</servlet-name>
<servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>
<init-param>
<param-name>org.apache.velocity.toolbox</param-name>
<param-value>/WEB-INF/toolbox.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>velocityView</servlet-name>
<url-pattern>*.vm</url-pattern>
</servlet-mapping>
</web-app>
在此示例的工具箱描述符(toolbox.xml)文件中,包含了可用的Velocity工具库中的两个通用工具,它们可在模板中访问: DateTool
和MathTool
。 这些工具使我们能够格式化日期和时间信息,并在模板中执行浮点数学运算,如清单21所示:
清单21.工具箱描述符,包括DateTool和MathTool
<?xml version="1.0"?>
<toolbox>
<tool>
<key>date</key>
<scope>application</scope>
<class>org.apache.velocity.tools.generic.DateTool</class>
</tool>
<tool>
<key>math</key>
<scope>application</scope>
<class>org.apache.velocity.tools.generic.MathTool</class>
</tool>
...
VelocityViewServlet
提供了一组常用的标准工具,如表1所示:
表1. VelocityViewServlet可用的标准工具
工具名称 | 描述 |
---|---|
LinkTool | 使用URI。 非常经常使用。 每当您在模板中创建可点击的链接时,都将需要此工具。 它可以生成URI的上下文相关部分。 |
CookieTool | 使模板能够创建或访问浏览器缓存的cookie。 |
ParameterParser | 简化了传入请求参数的解析。 |
还有两个高度专业化的,使用频率较低的工具,如表2所示:
表2.专用的VelocityViewServlet工具
工具名称 | 描述 |
---|---|
ViewRenderTool | 使模板能够解析包含VTL的字符串。 |
AbstractSearchTool | 提供一个骨架工具(必须使用您自己的自定义Java代码扩展),以实现在线搜索和搜索结果分页。 |
您可以使用http://localhost:8080/velview/variables.vm
URL来测试velview应用程序。 您应该检查模板源代码,以查看Velocity引擎, LinkTool
和CookieTool
在工作。
与Struts框架互操作
Struts是基于MVC模型的流行Web应用程序构建框架。 Struts的默认视图组件技术是JSP技术。 但是,您可以轻松地将Velocity集成为视图组件。 图1说明了Velocity的这种特定用法:
图1.将速度与Struts MVC框架集成
重要的是要注意,Velocity不会取代JSP技术。 相反,JSP技术和Velocity模板可以彼此协同工作。 要集成Velocity,请配置VelocityViewServlet
以处理.vm模板,如我们在部署VelocityViewServlet一节中所述。 这意味着.jsp文件将继续由容器(即Tomcat 5中的Jasper)处理,而任何.vm模板都将传递给Velocity。
Velocity Tools子项目的VelocityStruts
组件(请参阅参考资料 )具有将Velocity与Struts集成所需的一切。 VelocityStruts
提供了一组专用的Velocity工具,用于访问Velocity模板中特定于Struts的资源和信息。 表3列出了最常用的工具:
表3. VelocityStruts集成工具
工具名称 | 描述 |
---|---|
StrutsLinkTool | LinkTool的专用版本,可与Struts目标一起使用。 提供setAction() 和setForward() 来访问预配置的动作映射。 |
FormTool | 访问Struts的Form Bean。 |
ErrorsTool | 处理Struts错误消息,包括对国际化的支持。 |
MessageTool | 提供对Struts国际化支持的访问,更具体地说,是依赖于语言的消息资源。 |
还有一组专用于Struts 1.1中新功能的工具,如表4所示:
表4.专用的Struts 1.1访问工具
工具名称 | 描述 |
---|---|
SecureLinkTool | 与Struts 1.1的安全链接(SSL)扩展一起使用。 |
ActionMessagesTool | 提供对Struts 1.1的新ActionMessages 对象的访问。 |
TilesTool | 提供对Struts 1.1的Tiles扩展支持的访问。 |
ValidatorTool | 提供对Struts 1.1的Validator扩展的访问,生成代码以验证表单输入字段。 |
在webapps\struts-example
目录中,您将看到一个使用Struts而非JSP技术创建Struts页面的示例。 在这种情况下,我们用Struts替换了示例Web应用程序的第一个标题页。 您可能需要尝试更换其他页面。 下表描述了涉及的步骤。
- 将Velocity库复制到struts-example应用程序的
WEB-INF\lib
目录中。 使用Tomcat 5(在撰写本文时,最新版本为5.0.16)和Struts 1.1,您需要将以下JAR文件复制到webapps\struts-example\WEB-INF\lib
目录中:- velocity-tools-1.1-beta1.jar
- 速度1.4-rc1.jar
- 接下来,在Struts配置文件(
WEB-INF\struts-config.xml
)中,将Struts操作映射设置为转发到index.vm文件而不是index.jsp文件,如清单22所示:
清单22.修改Struts操作到\ index.vm<action path="/logoff" type="org.apache.struts.webapp.example.LogoffAction"> <forward name="success" path="/index.vm"/> </action>
- 在部署描述符
WEB-INF\web.xml
文件中,配置VelocityViewServlet
以处理.vm
文件。 还将欢迎文件设置为index.vm而不是index.jsp,如清单23所示:
清单23.修改struts示例Web应用程序的部署描述符<!-- Action Servlet Configuration --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml, /WEB-INF/struts-config-registration.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>velocity</servlet-name> <servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet </servlet-class> <init-param> <param-name>org.apache.velocity.toolbox</param-name> <param-value>/WEB-INF/toolbox.xml</param-value> </init-param> <init-param> <param-name>org.apache.velocity.properties</param-name> <param-value>/WEB-INF/velocity.properties</param-value> </init-param> </servlet> <!-- Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>velocity</servlet-name> <url-pattern>*.vm</url-pattern> </servlet-mapping> <!-- The Welcome File List --> <welcome-file-list> <welcome-file>index.vm</welcome-file> </welcome-file-list>
- 最后但并非最不重要的,从本文的源代码下载复制toolbox.xml和velocity.properties文件(请参阅相关的主题 )的
WEB-INF
目录下。
清单24中显示了新的index.vm文件。您可能需要将其与原始index.jsp文件进行比较。
清单24.通过使用index.vm Velocity模板进行Struts互操作
<html>
<head>
<title>$msg.get("index.title")</title>
</head>
<body bgcolor="white">
#if ( !$application.database)
<font color="red">
ERROR: User database not loaded -- check servlet container logs
for error messages.
</font>
<hr>
#end
<h3>$msg.get("index.heading")</h3>
<ul>
<li>
<a href="$link.setURI("editRegistration.do").addQueryData("action","Create")">
$msg.get("index.registration")
</a>
</li>
<li>
<a href="$link.setURI("logon.jsp")">
$msg.get("index.logon")
</a>
</li>
</ul>
<p> </p>
<a href="$link.setURI("tour.do")">
<font size="-1">$msg.get("index.tour")</font>
</a>
<p> </p>
<img src="$link.setURI("powered-by-logo.gif")" alt="Powered by Velocity"/>
</body>
</html>
在index.vm中,在整个模板中使用$msg
的消息工具来访问Struts依赖于语言环境的国际化资源。 这种方法消除了模板中大多数硬编码的字符串,从而将更改本地化到包含国际化字符串的资源包。
您可以使用VTL的条件#if
指令直接检查servlet上下文中是否存在数据库属性。 $application
引用可用于访问Servlet上下文中的任何属性( $request
, $response
和$session
也可用于访问其他Servlet API对象的属性)。
所述setURI()
的方法LinkTool
用于生成服务器端URI链接和struts的动作,以及向“由速度”的标志图像。 注意使用的addQueryData()
的方法LinkTool
附加动作信息附加到所得到的URI。
您可以通过启动Tomcat 5并访问http://localhost:8080/struts-example/
URL来测试Velocity页面。 注意它的工作方式与原始JSP版本相同。
结论
Velocity模板处理器可以直接集成到您自己的Java语言应用程序中,立即提供报告生成或模板处理功能。
将模板引擎扩展到Web应用程序后, VelocityServlet
可用于处理可动态生成HTML输出的Velocity模板。 Velocity工具项目为使用VelocityViewServlet
组件化Web层应用程序开发提供了进一步的支持。 VelocityViewServlet
为构建基于模板的基于Web的UI提供了一个方便的视图层。
使用MVC模型框架设计复杂的Web应用程序时,可以很容易地将Velocity作为视图/模板技术(以VelocityViewServlet
的形式)插入框架中。 对于流行的Jakarta Struts MVC框架,Velocity可以与基于JSP的视图技术一起使用,并且可以与任何模型技术进行互操作。
翻译自: https://www.ibm.com/developerworks/java/library/j-velocity/index.html