Velocity

前言

由于在做比较老的PE项目,代码模板大致类似,所以想做一个代码模板,进而想到了模板引擎。thymeleaf 与 velocity 以及FreeMarker 都可以完成需求,各种调研与试用之后决定使用并学习velocity,原因有以下几种:

  • thymeleaf评价较差,虽然是spring boot推荐的项目

  • 网上可以找到的性能测试结果,velocity与FreeMarker都比较强,thymeleaf 次之

  • thymeleaf相比velocity或者其他模板引擎的主要优势主要在于兼容xml语言,可以前端静态预览,但是相应的使用体检就变得较差,并且此功能对于我的代码生成器来说没什么作用

  • 现有的很多的代码生成器都是使用velocity(比如人人的代码生成器),可以用来参考

  • FreeMarker方面,与Velocity同样常用,功能也同样强大,但是感觉可读性不如Velocity,所以再三考虑最终选择了Velocity

注意,Spring Boot 1.4以后就不支持Velocity了,对于我来说这是一个致命缺点

简介

Apache Velocity 是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。可用于生成网页、SQL、PostScript以及其他模板的输出,其它系统的集成组件等。

应用场景

  • Web 应用:开发者在不使用 JSP 的情况下,可以用 Velocity 让 HTML 具有动态内容的特性

  • 源代码生成:Velocity 可以被用来生成 Java 代码、SQL 或者 PostScript等代码生成工具 自动

  • Email:很多软件的用户注册、密码提醒或者报表都是使用 Velocity 来自动生成的 转换 xml

相关资源

使用

添加依赖

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

使用步骤

  1. 初始化Velocity,单例,无需多次执行

  2. 创建上下文对象

  3. 添加变量到Context对象中

  4. 选择模板

  5. Merge 合并模板与数据,完成输出

import java.io.StringWriter;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.MethodInvocationException;

// 初始化Velocity
Velocity.init();
// 创建上下文对象
VelocityContext context = new VelocityContext();
// 添加变量到Context对象中
context.put( "name", new String("Velocity") );
// 选择模板
Template template = null;
try {
  template = Velocity.getTemplate("mytemplate.vm");
} catch( ResourceNotFoundException rnfe ){
  // couldn't find the template
} catch( ParseErrorException pee ) {
  // syntax error: problem parsing the template
} catch( MethodInvocationException mie ) {
  // something invoked in the template
  // threw an exception
} catch( Exception e ){ }

// Merge 合并模板与数据,完成输出
StringWriter sw = new StringWriter();
template.merge( context, sw );

使用规约

不得使用``org.apache.velocity.runtime 包下的Runtime, RuntimeConstants, RuntimeSingleton or RuntimeInstance`,这些类仅供Velocity内部使用

可以使用的是org.apache.velocity.app 下的所有类,如果此包下缺少必要的功能,建议修改

单例与非单例

Velocity.init()方法会创建一个单例的VelocityEngine模板引擎对象,所以,他们拥有相同的properties配置,有时需要不同的配置,此时可以通过手动创建多例模板引擎对象来实现:

VelocityEngine ve = new VelocityEngine();
ve.setProperty(VelocityEngine.RUNTIME_LOG_NAME, "mylog");
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();
Template t = ve.getTemplate("foo.vm");

Context上下文

Context是Velocity核心,是Java层与模板层直接数据的载体。你的模板需要什么数据,只需要将其放入到其中,由模板引擎合并。

Context由VelocityContext类定义,主要提供了两个方法:

public Object put(String key, Object value);
public Object get(String key);

支持#foreach

要想支持模板的#foreach循环,传入的Java对象,会依据情况做出相应处理:

  • 数组, java.util.List 遍历方式一致

  • java.util.Collection,将会使用iterator()方法遍历

  • java.util.Map,依赖于接口的values()方法来获取Collection接口,并通过iterator()遍历

  • java.util.Iterator,小心使用,迭代器不可重置性,迭代器只可使用一次,意味着多个#foreach只有第一个会成功

  • java.util.Enumeration, 通过枚举的hasMoreElements()nextElement()方法操作,此方式与Iterator由一样的问题

放入'静态类'

有些工具类不可以被实例化,但是提供了一些公共静态方法,我们可以将其class对象放入Context中,以便使用:

context.put("Math", Math.class);

Context Chaining

可以翻译为连续上下文,多个上下文之间含有链式关系,如下:

VelocityContext context1 = new VelocityContext();
context1.put("name","Velocity");
context1.put("project", "Jakarta");
context1.put("duplicate", "I am in context1");

VelocityContext context2 = new VelocityContext( context1 );
context2.put("lang", "Java" );
context2.put("duplicate", "I am in context2");

template.merge( context2, writer );

上述输出结果为 duplicate= "I am in context2" 。并且context2中包含所有context1 的变量,但是context1中的变量duplicate仍然存在,并且值仍为I am in context1

此功能常用于分层数据访问以及工具集。

Velocity

Velocity类是一个帮助类,帮助用户轻松使用模板引擎。**Velocity运行时引擎是一个单例,同一JVM中运行所有Velocity用户资源、日志以及其他服务。**所以运行时引擎只会初始化一次,其余的尝试将会被忽略。

配置模板引擎

Velocity运行时引擎提供了五种常用方法,用于配置引擎:

  • setProperty( String key, Object o ) 设置属性配置

  • Object getProperty( String key ) 获取属性配置

  • init() 使用默认配置初始化引擎

  • init( Properties p ) 使用指定的Properties对象初始化引擎

  • init( String filename ) 指定配置文件路径初始化引擎

重复调用init方法无效,Velocity只会被初始化一次

渲染模板

Velocity 针对模板渲染提供了以下几个方法:

// 使用context作为参数渲染模板并输入到write流中,其中instring以及instream是模板信息,logTag则是在发生错误时用作日志消息的模板名称的字符串
evaluate( Context context, Writer out, String logTag, String instring )
evaluate( Context context, Writer writer, String logTag, InputStream instream )

// 直接访问velocimacro, vmName代表宏的名称、namespace代表宏的命名空间,调用velocimacro args的键
invokeVelocimacro( String vmName, String namespace, String params[], Context context, Writer writer )

// 建议使用此种方式,根据模板名称解析合并模板, 即从模板根路径下寻找模板
mergeTemplate( String templateName, Context context, Writer writer )

// 根据模板名称判断模板是否存在
boolean templateExists( String name )

模板根路径是由p.setProperty("resource.loader.file.path", "/opt/templates");属性决定的

异常

在解析时,Velocity可能会抛出异常,这些异常集成RuntimeException:

  • ResourceNotFoundException 找不到模板资源

  • ParseErrorException 解析时发现VTL语法错误

  • TemplateInitException 模板初始化异常,通常是宏和指令初始化的问题

  • MethodInvocationException: 模板调用的方法抛出异常

日志

Velocity2.0开始使用SLF4J作为日志门面。启用日志需要:

  1. 保证slf4j的jar存在

  2. 保证slf4j具体实现的jar存在

Velocity的日志皆是以 org.apache.velocity作为父路径的,其中包含如下几个子路径:

  • directive, and directive.指令相关日志

  • parser 模板解析日期

  • loader, and loader. 资源加载日志

  • macro 宏相关

  • rendering 模板渲染的相关内容,包含内省、方法调用

  • event 事件日志

如果想要自己定义日志文件名称,可以通过runtime.log.name属性指定

缩进控制

2.o 可以通过``parser.space_gobbling 属性控制缩进,(属性名称翻译空间吞噬???)共有

  • none 无空间吞噬

  • bc (aka backward compatible) 向后兼容

  • lines 默认值

  • structured 结构化

四种可选值。

none

不吞噬任何空间,指令所在行附近的空间,不做任何删除操作:

#set($foo = 'foo')↲
<table>↲
</table>↲
↲ ## 此行仍然保留原有的换行
<table>↲
</table>↲

bc

此模式会吃掉指令后面所有的空白符:

#set($foo = 'foo')↲
<table>↲
</table>↲
<table>↲
</table>↲

lines

吃掉当前行的空白符:

#set($foo = 'foo')↲
<table>↲
</table>↲
<table>↲
</table>↲

structured

http://velocity.apache.org/engine/2.1/developer-guide.html#space-gobbling

没看明白,待解决

ResourceLoader

资源加载是Velocity的重要一部分,它负责加载模板或者是非模板资源(#include),主要位于包org.apache.velocity.runtime.resource.loader。Velocity目前共有四种资源加载器:

  • FileResourceLoader

    从文件获取资源,包含属性

    • resource.loader.file.path=rootpath1,path2,path3.. 资源加载根路径

    • resource.loader.file.cache=true/false 加载资源是否缓存

    • resource.loader.file.modification_check_interval=100每隔100s检查一次配置是否需要更新

    • 这是默认资源加载器

  • JarResourceLoader

    从特定的jar包中获取资源,与

    FileResourceLoader

    很相似,只是绑定到了jar中

    • resource.loader.jar.pathresource.loader.file.path作用一致

    • 其他属性与 FileResourceLoader一致

  • ClasspathResourceLoader 从类加载器中获取资源,通常是放入类路径下的模板文件,通常用于Servlet容器

  • URLResourceLoader 

    从URL连接获取资源:

    • resource.loader.url.root url根路径

    • resource.loader.url.cache 是否缓存

    • resource.loader.url.modification_check_interval 检查间隔 秒

    • resource.loader.url.timeout 超时时间 -1 代表超时时间为正无穷

  • DataSourceResourceLoader 从数据库中获取

ApplicationAttribute

应用程序属性是一种能够和运行时实例相关联(通过Velocity引擎或者Velocity单例)的键值对。它可以被Velocity引擎中任何运行时实例访问。这个特性是为了在应用层和Velocity引擎的特定部件之间通信的应用程序而设计的,比如日志记录器,资源加载器,资源管理器 。

举例,可以通过ApplicationAttribute 设置UrlResourceLoader的超时时间,外部在使用应用程序时,可以改变这个值,像是程序配置入口

Velocity类中包含操作ApplicationAttribute的相关方法:

  • Velocity.setApplicationAttribute( Object key, Object value )

  • Velocity.getApplicationAttribute( Object key )

调用时间没有要求,不一定要在init()方法之前调用。

事件处理

Velocity含有细粒度的事件处理系统,允许自定义引擎的操作。这些事件是同步的。所有事件处理处理程序接口都位于org.apache.velocity.app.event.implement包下,具体使用需要查看javadoc,这里只列举几例:

IncludeEventHandler

IncludeEventHandler是针对include指令的事件监听:

public IncludeEventHandler extends EventHandler {
    public String includeEvent( Context context,
                                String includeResourcePath, 
                                String currentResourcePath, 
                                String directiveName );
}

共有两个实现类:

  • IncludeNotFound (org.apache.velocity.app.event.implement) 未找到资源事件处理

  • IncludeRelativePath (org.apache.velocity.app.event.implement)

方法参数转换

UberspectorImpl 或者SecureUberspector会根据需要对方法参数进行类型转换:

  • boolean to number: true 1, false 0

  • boolean to string: "true" and "false"

  • number to boolean: 0 false, 其他 true

  • number to string

  • string to boolean: "true" 转为 true, 其他字符串将会被转换为false(包含"false") false

  • string to number: 如果字符串不是数字格式,则会抛出异常

  • 字符串下转型 : 如果不符合预期数字类型,抛出异常

  • string to enum constant: 如果不是预期枚举,抛出异常

  • string to locale (since 2.1)

下图中, implicit代表Java隐士转换,none代表无法转换,strict代表严格转换(通常指代相同类型), 而explicit代表期望转换(转换失败会抛出异常)

扩展类型转换

扩展类型转换,可以通过 Converter<T>接口实现:

package mypackage;

import java.util.Date;
import org.apache.velocity.util.introspection.*;

public class MyUberspector extends UberspectorImpl
{
    public void init()
    {
        super.init();
        // 注册转换器
        getConversionHandler().addConverter(Integer.class, Date.class, new ConvertToDate());
        getConversionHandler().addConverter(Long.class, Date.class, new ConvertToDate());
    }
	
	// 日期转换
    public static class ConvertToDate extends Converter<Date>
    {
        @Override
        public Date convert(Object o)
        {
            return new Date(((Number)o).longValue());
        }
    }
}

除了通过继承UberspectorImpl类注册类型转换器,还可以

  • 继承org.apache.util.introspection.TypeConversionHandlerImpl类,并在构造函数中添加转换器(2.0废弃)

  • 配置属性runtime.conversion.handler.instance=apache.util.introspection.TypeConversionHandler

编码

Velocity允许在模板的基础上指定编码:

org.apache.velocity.app.Velocity

public static Template getTemplate(String name, String encoding)

public static boolean mergeTemplate( String templateName, String encoding, Context context, Writer writer )

集成到JSR223

Velocity可以集成到Java Scripting Language Framework 即 JSR223中:

// get script manager, create a new Velocity script engine factory and get an engine from it
ScriptEngineManager manager = new ScriptEngineManager();
manager.registerEngineName("velocity", new VelocityScriptEngineFactory());
ScriptEngine engine = manager.getEngineByName("velocity");

System.setProperty(VelocityScriptEngine.VELOCITY_PROPERTIES, "path/to/velocity.properties");
String script = "Hello $world";
Writer writer = new StringWriter();
engine.getContext().setWriter(writer);
Object result = engine.eval(script);
System.out.println(writer);

VTL详解

Velocity Template Language,是Velocity的模板语言。

  1. velocity的模板文件以.vm为拓展名

  2. 模板中的所有关键字都以#号开头,可以加入大括号#{set xx}#{if} #{else}

  3. 模板中的所有变量都已$符号开头,同样可以加入大括号 ${name}

  4. 如果想要输出$或者#需要在前面加上\进行转移,相同的,如果想要输出\则需要\\

  5. $数字可以直接输出,比如$1 输出为$1

解析模板

 // 初始化模板引擎
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();

// 使用文件创建模板对象
Template t = ve.getTemplate("hello-velocity.vm");

// 初始化VelocityContext对象
VelocityContext ctx = new VelocityContext();
ctx.put("name", "Velocity");
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
ctx.put("list", list);

// 解析模板并输出结果
StringWriter sw = new StringWriter();
t.merge(ctx, sw);
System.out.println(sw.toString());

注释

单行注释

## 这是单行注释

多行注释

#*
这是多行注释
*#

文档注释

#**
  这个代码是xx锤子用的
information:
@version 1.1
@author yangsx
*#

变量操作

velocity 中含有变量的概念,变量类型为弱类型。在执行模板时,模板可以从VelocityContext对象中获取其中存放的值,也可以从#set($foo = "bar")定义的变量中获取值。

变量命名规范

Velocity变量与java类似,只允许字母、下划线以及数字组成,不能以数字开头,所以$1abc的输出结果就是$1abc

变量/属性输出

 // 获取模板文件
Template t = ve.getTemplate("基础语法.vm");

// 设置变量
VelocityContext ctx = new VelocityContext();
Obj obj = new Obj();
obj.setString("张三");
obj.setInteger(100);
obj.setArray(new String[]{"唐", "送", "元", "明", "清"});
obj.setList(Arrays.asList("魏", "晋", "南朝", "北朝"));
obj.setMap(new HashMap<String, String>(){{
    this.put("A", "1");
    this.put("B", "2");
    this.put("C", "3");
    this.put("D", "4");
}});
ctx.put("obj", obj);

StringWriter sw = new StringWriter();
t.merge(ctx, sw);

对应的模板为:

变量的类型:

1. 字符类型:$obj.string
2. 数字类型:$obj.integer
3. 数组类型:$obj.array, 第0个元素为 $obj.array[0]
4. 集合类型:$obj.list, 第0个元素为 $obj.list[0]
5. map类型:$obj.map, key为A的值为 $obj.map.A
7. 引用类型直接输出toString方法: $obj
8. 获取方法返回值: $obj.getString()

得到的输出结果为:

变量的类型:

1. 字符类型:张三
2. 数字类型:100
3. 数组类型:[Ljava.lang.String;@45afc369, 第0个元素为 唐
4. 集合类型:[魏, 晋, 南朝, 北朝], 第0个元素为 魏
5. map类型:{A=1, B=2, C=3, D=4}, key为A的值为 1
7. 引用类型直接输出toString方法: 基础语法.Obj(string=张三, integer=100, array=[唐, 送, 元, 明, 清], list=[魏, 晋, 南朝, 北朝], map={A=1, B=2, C=3, D=4})
8. 获取方法返回值: 张三

name是name是{name}的简写 二者没有什么实际区别

数组操作

除了可以通过方括号获取数组元素,Velocity引擎也提供了几个方便的方法,便于我们操作数组:

$myarray.isEmpty() or $myarray.empty
$myarray.size()
$myarray.get(2)
$myarray.set(1, 'test')

默认缺省值

在展示变量或者属性时,不可避免的出现空值,可以使用|设置缺省值:

My name is ${name|'John Doe'}

属性检测规则

假设有$obj.name,Velocity模板引擎会依次从以下几个地方从obj对象中寻找此变量的值:

  1. getname()方法

  2. getName()方法

  3. get("name")方法,通常用于map

  4. isName()方法

如果是$obj.Name属性,则会略有不同:

  1. getName()方法

  2. getname()方法

  3. get("Name")方法,通常用于map

  4. isName()方法

变量定义赋值

此外,Velocity 也支持在模板内定义变量, 可以使用set关键字声明一个变量:

#set(${name} = "velocity")

其中"velocity"就是变量值,你可以设置:

  • "Hello World" 字符串字面量

  • 10 数字字面量

  • ["唐", "宋", "元"] 数组类型

  • 属性、方法引用

  • ArrayList、Map

方法调用

可以在VTL中调用传入的Java对象的public方法:

$customer.getAddress()
$purchase.getTotal()
$page.setTitle( "My Home Page" )
$person.setAttributes( ["Strange", "Weird", "Excited"] )

支持vararg methods

## void setAttributes(String... args)
$person.setAttributes("Strange", "Weird", "Excited")

渲染

Velocity中的所有动态内容,比如属性、变量等,最终都会被渲染为字符串。

严格渲染模式

Strict渲染模式适用于某些特殊用途,在此模式下,任何模棱两可的表达方式,都会被模板引擎视为异常:

  • 变量未定义或者 中不存在,引用此变量将会抛出异常

  • 此变量未定义或者VelocityContext中不存在,或者此变量为null,引用此变量的属性会为null

  • #if指令如果引用变量未定义或者为null,则返回false: #if ($foo)#end ## False# if(!$foo) #end ## True

指令详解

指令以 #开头~

set

set指令用于给变量赋值或者定义变量,被赋予的值可以是:

  • Number literal 数字字面量

    • #set( $monkey.Number = 123 )

  • String literal 字符串字面量:

    • #set( $monkey.Friend = "monica" )

  • ArrayList

    • #set( $monkey.Say = ["Not", $my, "fault"] )

    • $monkey.Say.get(0)

  • Map

    • #set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"})

    • $monkey.Map.banana

    • $monkey.Map.get("banana")

  • Variable reference 变量引用

    • #set( $monkey = $bill )

  • Property reference 属性引用

    • #set( $monkey.Blame = $whitehouse.Leak )

  • Method reference 方法引用

    • #set( $monkey.Plan = $spindoctor.weave($web) )

右侧运算

除此之外,右侧值也可以进行简单的运算:

#set( $value = $foo + 1 )
#set( $value = $bar - 1 )
#set( $value = $foo * $bar )
#set( $value = $foo / $bar )

双引号和单引号

#set( $foo = "bar" )
#set( $a = '$foo' )
#set( $b = "$foo" )
$a ## $foo
$b ## bar

双引号会解析引号内的变量, 此功能可以通过velocity.propertiesstringliterals.interpolate=false属性关闭。

如果有大段代码不需要解析,可以通过如下方式设置:

#[[
#foreach ($woogie in $boogie)
  不会被解析 $woogie
#end
]]#

输出结果:

#foreach ($woogie in $boogie)
  不会被解析 $woogie
#end

条件判断

if/elseif/else

#if( $foo < 10 )
    xxx
#elseif( $foo == 10 )
    xxx
#elseif( $bar == 6 )
    xxx 
#else
    xxx 
#end

if的条件的判断遵循以下规则:

  • boolean 类型:true/false

  • string 类型:null与空字符被视为false

  • number类型: 0 视为false,其他被视为true

  • 集合类型: 集合长度size()为0

逻辑运算符

  • 逻辑与: #if( $foo && $bar )

  • 逻辑或: #if( $foo || $bar )

  • 逻辑非: #if( !$foo )

循环

<ul>
#foreach( $product in $allProducts )
    <li>$product</li>
#end
</ul>

此种方式还可以对Java对象中的所有属性进行遍历,操作方式与操作map一致:

<ul>
#foreach( $key in $allProducts.keySet() )
    <li>Key: $key -> Value: $allProducts.get($key)</li>
#end
</ul>

判断循环是否是第一次

#foreach( $customer in $customerList )
    #if( $foreach.first ) There are customer: #end
#end

判断循环是否是最后一次:

#foreach( $customer in $customerList )
    #if( $foreach.hasNext ),#end
#end

判断循环次数是否为0:

#foreach( $customer in $customerList )
#else
空的集合
#end

获取当前索引(从0开始):

#foreach( $customer in $customerList )
当前索引为:$foreach.index
#end

获取当前循环到底几次(从1开始)

#foreach( $customer in $customerList )
当前索引为:$foreach.count
#end

设置循环次数,防止故障循环逻辑:

## -1代表无限制次数
directive.foreach.max_loops = -1

控制语句

break

结束当前的执行范围,也是最直接的范围,比如#foreach #parse#evaluate, #define, #macro或者根范围。

除此之外,break也可以跳出到指定的范围:比如,#break($macro), #break($foreach)

stop

停止执行模板,通常用于调试或者提示,参数可以设置提示信息: #stop('$foo 不在context中,无法继续执行')

灵活引用模板

include

include指令可以导入本地文件,并将其插入到指定的位置,本地文件的位置只能为TEMPLATE_ROOT定义的路径下:

#include( "one.txt" )
#include( "one.gif","two.txt","three.htm" )
#include( "greetings.txt", $seasonalstock )

parse

include可以引入本地的资源,而parse可以解析本地的VTL模板:

#parse( "parsefoo.vm" )

define

为变量赋值一个VTL代码块:

## 定义一个名称为 block的变量,此变量是一个VTL块,块中的内容为  Hello $who
#define( $block )Hello $who#end
## 为块中的$who设置值
#set( $who = 'World!' )
## 输出块的值
$block

velocimacros

#macro指令允许模板设计者定义VTL模板重复段,定义与使用宏的方式如下:

## 定义
#macro( d )
<tr><td></td></tr>
#end
## 使用
#d()

宏可以包含body,使用时需要制定body,如果不指定默认为空:

## 定义包含body的宏
#macro( d )
<tr><td>$!bodyContent</td></tr>
#end
## 使用
#@d()我是内容体#end
#d()  ## 没有数据的空的宏

宏也可以指定任意数量的参数,但是调用时必须指定相同数量的参数:

##定义一个包含两个参数的宏
#macro( macroname $color $somelist )
    #foreach( $something in $somelist )
        <tr><td bgcolor=$color>$something</td></tr>
    #end
#end

##使用
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
    #macroname( $color $greatlakes )
</table>

macroname是定义的宏的名称

参数类型

VTL的宏共支持如下几种参数类型:

  • Reference : 以$开头的任何变量

  • String literal : 字符串字面量

  • Number literal : 数字字面量

  • IntegerRange : 数字范围,比如[1..2] , [$foo .. $bar]

  • ObjectArray : 数组,[ "a", "b", "c"]

  • boolean

配置属性

关于Velocimacro,有相关常用属性需要了解,以便灵活应用:

  • velocimacro.inline.allow是否允许Velocimacro,值为true/false

  • velocimacro.library.autoreload 控制Velocimacro是否自动加载,默认false,设置为true时,将会检查velocimacro 库是否发生更改,必要时进行重新加载。(前置条件:关闭缓存resource.loader.file.cache = false),用于开发环境

  • velocimacro.library.path 模板库路径,默认会去查找velocimacros.vtl

  • velocimacro.inline.replace_global,true/false,是否覆盖全局的macro(velocimacro.library.path中的macro),如果macro名称相同

  • velocimacro.inline.local_scope,true/false,如果为true,当前模板定义的micro尽可以被当前模板使用,用于限定作用域。

  • 当两个模板定义了一个相同名称的宏时,需要将 velocimacro.inline.replace_globalvelocimacro.inline.local_scope全都设置为true

参考

最后更新于