Contents

Apache Velocity 简介

1.概述

Velocity 是一个基于 Java 的模板引擎。

它是一个开源 Web 框架,旨在用作 MVC 架构中的视图组件,它提供了一些现有技术(如 JSP)的替代方案。

Velocity 可用于生成 XML 文件、SQL、PostScript 和大多数其他基于文本的格式。

在本文中,我们将探讨如何使用它来创建动态网页。

2. Velocity 是如何工作的

Velocity 的核心类是VelocityEngine

它使用数据模型和速度模板编排读取、解析和生成内容的整个过程。

简而言之,对于任何典型的速度应用程序,我们需要遵循以下步骤:

  • 初始化速度引擎
  • 阅读模板
  • 将数据模型放入上下文对象中
  • 将模板与上下文数据合并并渲染视图

让我们按照这些简单的步骤来看一个示例:

VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
   
Template t = velocityEngine.getTemplate("index.vm");
    
VelocityContext context = new VelocityContext();
context.put("name", "World");
    
StringWriter writer = new StringWriter();
t.merge( context, writer );

3. Maven依赖

要使用 Velocity,我们需要在 Maven 项目中添加以下依赖项:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
    </dependency>
<dependency>
     <groupId>org.apache.velocity</groupId>
     <artifactId>velocity-tools</artifactId>
     <version>2.0</version>
</dependency>

这两个依赖项的最新版本可以在这里:velocityvelocity-tools

4. Velocity 模板语言

Velocity 模板语言 (VTL) 通过使用 VTL 引用提供了将动态内容合并到网页中的最简单和最干净的方法。

速度模板中的 VTL 引用以*$开头,用于获取与该引用关联的值。VTL 还提供了一组指令,可用于操作 Java 代码的输出。这些指令以#* 开头。

4.1.参考

Velocity 中有三种类型的引用,变量,属性和方法:

  • 变量——在页面中使用*#set*指令或从 Java 对象的字段返回的值定义:
#set ($message="Hello World")
  • 属性——引用对象中的字段;它们还可以引用属性的getter方法:
$customer.name
  • 方法– 指 Java 对象上的方法:
$customer.getName()

每个引用产生的最终值在呈现到最终输出时都会转换为字符串。

4.2. 指令

VTL 提供了丰富的指令集:

  • set – 可用于设置参考值;此值可以分配给变量或属性引用:
#set ($message = "Hello World")
#set ($customer.name = "Brian Mcdonald")
  • 条件—— #if、#elseif和*#else*指令提供了一种基于条件检查生成内容的方法:
#if($employee.designation == "Manager")
    <h3> Manager </h3>
#elseif($employee.designation == "Senior Developer")
    <h3> Senior Software Engineer </h3>
#else
    <h3> Trainee </h3>
#end
  • loops#foreach指令允许循环对象集合:
<ul>
    #foreach($product in $productList)
        <li> $product </li>
    #end
</ul>
  • include - #include元素提供将文件导入模板的能力:
#include("one.gif","two.txt","three.html"...)
  • parse#parse语句允许模板设计者导入另一个包含 VTL 的本地文件;然后 Velocity 将解析内容并呈现它:
#parse (Template)
  • evaluate#evaluate指令可用于动态评估 VTL;这允许模板在渲染时评估字符串,例如国际化模板:
#set($firstName = "David")
#set($lastName = "Johnson")
#set($dynamicsource = "$firstName$lastName")
#evaluate($dynamicsource)
  • break - #break指令停止当前执行范围的任何进一步呈现(即*#foreach*,#parse
  • stop#stop指令停止模板的任何进一步渲染和执行。
  • velocimacros#macro指令允许模板设计者定义 VTL 的重复段:
#macro(tablerows)
    <tr>
        <td>
        </td>
    </tr>
#end

这个宏现在可以作为*#tablerows()*放在模板中的任何位置:

#macro(tablerows $color $productList)
    #foreach($product in $productList)
        <tr>
            <td bgcolor=$color>$product.name</td>
        </tr>
    #end
#end

4.3. 其它功能

  • math – 一些内置的数学函数,可以在模板中使用:
#set($percent = $number / 100)
#set($remainder = $dividend % $divisor)
  • 范围运算符– 可以与*#set#foreach* 结合使用:
#set($array = [0..10])
#foreach($elem in $arr)
    $elem
#end

5. Velocity Engine

Velocity Engine 的主要工作是根据模板生成内容。

引擎本身不包含任何与网络相关的功能。要实现 Web 应用程序,我们需要使用 servlet 或基于 servlet 的框架。

Velocity 提供了一个开箱即用的实现VelocityViewServlet,它是velocity-tools 子项目的一部分。

为了利用VelocityViewServlet提供的内置功能,我们可以从VelocityViewServlet扩展我们的 servlet并覆盖*handleRequest()*方法:

public class ProductServlet extends VelocityViewServlet {
    ProductService service = new ProductService();
    @Override
    public Template handleRequest(
      HttpServletRequest request, 
      HttpServletResponse response,
      Context context) throws Exception {
      
        List<Product> products = service.getProducts();
        context.put("products", products);
        return getTemplate("index.vm");
    }
}

6.配置

6.1.网页配置

现在让我们看看如何在web.xml中配置VelocityViewServlet

我们需要指定可选的初始化参数,包括velocity.propertiestoolbox.xml

<web-app>
    <display-name>apache-velocity</display-name>
      //...
       
    <servlet>
        <servlet-name>velocity</servlet-name>
        <servlet-class>org.apache.velocity.tools.view.VelocityViewServlet</servlet-class>
        <init-param>
            <param-name>org.apache.velocity.properties</param-name>
            <param-value>/WEB-INF/velocity.properties</param-value>
        </init-param>
    </servlet>
        //...
</web-app>

我们还需要为这个 servlet 指定映射。所有对速度模板 ( *.vm ) 的请求都需要由速度 servlet 提供服务:

<servlet-mapping>
    <servlet-name>velocityLayout</servlet-name>
    <url-pattern>*.vm</url-pattern>
</servlet-mapping>

6.2. 资源加载器

Velocity 提供灵活的资源加载系统。它允许一个或多个资源加载器同时运行:

  • FileResourceLoader
  • JarResourceLoader
  • ClassPathResourceLoader
  • URLResourceLoader
  • DataSourceResourceLoader
  • WebappResourceLoader

这些资源加载器在velocity.properties 中配置:

resource.loader=webapp
webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader
webapp.resource.loader.path = 
webapp.resource.loader.cache = true

7. Velocity 模板

Velocity 模板是编写所有视图生成逻辑的地方。这些页面是使用 Velocity 模板语言 (VTL) 编写的:

<html>
    ...
    <body>
        <center>
        ...
        <h2>$products.size() Products on Sale!</h2>
        <br/>
            We are proud to offer these fine products
            at these amazing prices.
        ...
        #set( $count = 1 )
        <table class="gridtable">
            <tr>
                <th>Serial #</th>
                <th>Product Name</th>
                <th>Price</th>
            </tr>
            #foreach( $product in $products )
            <tr>
                <td>$count)</td>
                <td>$product.getName()</td>
                <td>$product.getPrice()</td>
            </tr>
            #set( $count = $count + 1 )
            #end
        </table>
        <br/>
        </center>
    </body>
</html>

8. 管理页面布局

Velocity 为基于 Velocity Tool 的应用程序提供了简单的布局控制和可定制的错误屏幕。

VelocityLayoutServlet封装了此功能以呈现指定的布局。VelocityLayoutServletVelocityViewServlet 的扩展。

8.1. 网页配置

让我们看看如何配置VelocityLayoutServlet。servlet 被定义用于拦截速度模板页面的请求,并且布局特定属性在velocity.properties文件中定义:

<web-app>
    // ...
    <servlet>
        <servlet-name>velocityLayout</servlet-name>
        <servlet-class>org.apache.velocity.tools.view.VelocityLayoutServlet</servlet-class>
        <init-param>
            <param-name>org.apache.velocity.properties</param-name>
            <param-value>/WEB-INF/velocity.properties</param-value>
        </init-param>
    </servlet>
    // ...
    <servlet-mapping>
        <servlet-name>velocityLayout</servlet-name>
        <url-pattern>*.vm</url-pattern>
    </servlet-mapping>
    // ...
</web-app>

8.2. 布局模板

布局模板定义了速度页面的典型结构。默认情况下,VelocityLayoutServlet在布局文件夹下搜索*Default.vm *。覆盖少数属性可以更改此位置:

tools.view.servlet.layout.directory = layout/
tools.view.servlet.layout.default.template = Default.vm

布局文件由页眉模板、页脚模板和一个速度变量*$screen_content* 组成,它呈现请求的速度页面的内容:

<html>
    <head>
        <title>Velocity</title>
    </head>
    <body>
        <div>
            #parse("/fragments/header.vm")
        </div>
        <div>
            <!-- View index.vm is inserted here -->
            $screen_content
        </div>
        <div>
            #parse("/fragments/footer.vm")
        </div>
    </body>
</html>

8.3. 请求屏幕中的布局规范

特定屏幕的布局可以定义为页面开头的速度变量。这是通过将这一行放在页面中来完成的:

#set($layout = "MyOtherLayout.vm")

8.4. 请求参数中的布局规范

我们可以在查询字符串layout=MyOtherLayout.vm中添加一个请求参数,VLS 会找到它并在该布局内渲染屏幕,而不是搜索默认布局。

8.5. 错误屏幕

可以使用速度布局实现自定义错误屏幕。VelocityLayoutServlet提供了两个变量*$error_cause$stack_trace*来呈现异常细节。

错误页面可以在velocity.properties文件中配置:

tools.view.servlet.error.template = Error.vm