Velocity源码分析(一)——概述

原文链接 :http://coderj.org/blog/2011/08/19/velocity_overview/

一、概述

Velocity模板引擎处理机制分为五个基本步骤:

  1. 引擎初始化,通过设置的引擎属性初始化引擎,包括国际化支持,ResourceLoader设置,字符编码等。
  2. 获取并解析模板文件,首先通过资源加载器(ResourceLoader)将模板文件加载到内存(转化为InputStream),然后通过AST(Abstract Syntax Tree)解析器将InputStream解析为一个AST。
  3. 创建一个Context
  4. 将模板渲染所需的参数放入context
  5. 执行模板渲染,产生输出流。渲染过程中通过遍历该模板对应的AST,调用相应节点的处理器执行渲染。

整个处理流程如下图所示:

二、详细渲染流程

下面以一个简单的模板template.vm为例,详细解释渲染过程。
VelocityMergeTest.java

public class VelocityMergeTest {

	public static void main(String[] args) {
		VelocityEngine ve = new VelocityEngine();
		ve.setProperty(Velocity.RESOURCE_LOADER, "class");
		ve.setProperty("class.resource.loader.class",
				"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		try {
			// 引擎初始化
			ve.init();
			// 加载解析模板
			Template tp = ve.getTemplate("template.vm");
			// 创建context
			Context context = new VelocityContext();
			// 设置Context中参数值
			context.put("foo", "VV");
			StringWriter writer = new StringWriter();
			// 执行渲染
			tp.merge(context, writer);
			System.out.println(writer.toString());
		} catch (Exception e) {
		}
	}
}

 template.vm:

<html>
   <body>
     Hello $foo world!
    </body>
</html>

2.加载解析模板

当执行ve.getTemplate(“template.vm”)时,首先通过ResourceLoader将tempalte加载为InputStream,然后通过Parser生成如下Token集合:
{[<html> <body> Hello], [$foo], [world! </body> </html> ]},
可以发现velocity根本不关系模板最终要渲染出来的是html还是什么的其他的东西,也就以为这所有的html标签对velocity来讲都是纯文本。
最终构建的AST如下

根节点下有三个子节点:

  1. [<html> <body> Hello]对应的ASTText节点;
  2. [$foo]对应的ASTReference节点;
  3. [world! </body> </html> ]对应的ASTText节点

Velocity引擎在这里有个优化策略,可以针对生成的语法树进行cache。

3.创建context并设置参数

Context context = new VelocityContext();
context.put(“foo”, “VV”);
创建一个context,并在其中放入一个foo=VV的参数。

4.执行渲染

当执行tp.merge(context, writer);时,模板遍历其对应的AST树,执行每个节点的渲染过程。如ASTText节点只是简单的将文本写入writer。 ASTReference节点需要从context中获取引用的参数foo的值VV,将$foo替换,并写入到writer中。Velocity的AST 中有多种节点,如ASTIdentitor等,有些需要反射机制处理。当整个AST遍历结束,也就意味着模板渲染结束,渲染的结果位于writer流中。

三、关于AST解析

Velocity作为模板语言,其核心在与模板文件的解析,构建AST。Velocity的解析器是通过JavaCC构建 的,JavaCC(Java Complier Complier)是一个用于生成解析器的工具,可以根据语法定义(.jj文件)生成用于校验一份文本是否符合该语法定义的java代码。JJTree是 JavaCC中提供的一种根据语法定义(.jjt文件)生成构建符合该语法定义的文本的语法树的java代码的工具。
Velocity源码包中提供了用于构建velocity语法解析的的jjt文件,位于src/parser/Parser.jjt。可以自己手动从源码构建Velocity的解析器。步骤如下:
1.下载安装JavaCC,到http://javacc.java.net/下载即可,velocity的解析器需要3.2版本以上。下载后解压即可。
2.使用JJTree生成节点定义:
$ javacc-5.0/bin/jjtree Parser.jjt
这一过程中会生成节点定义的Java文件和Parser.jj语法定义文件
3.使用JavaCC生成解析器
$ javacc-5.0/bin/javacc Parser.jj
最终会生成Parser.java解析器和个节点定义。

你可能感兴趣的:(velocity)