惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tailwind CSS Blog
博客园 - Franky
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
GbyAI
GbyAI
Y
Y Combinator Blog
Microsoft Azure Blog
Microsoft Azure Blog
Blog — PlanetScale
Blog — PlanetScale
博客园 - 叶小钗
罗磊的独立博客
The GitHub Blog
The GitHub Blog
H
Help Net Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Engineering at Meta
Engineering at Meta
Martin Fowler
Martin Fowler
Spread Privacy
Spread Privacy
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
N
Netflix TechBlog - Medium
T
The Exploit Database - CXSecurity.com
云风的 BLOG
云风的 BLOG
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
Cyberwarzone
Cyberwarzone
T
Threatpost
T
Threat Research - Cisco Blogs
Recent Announcements
Recent Announcements
T
Tor Project blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
L
Lohrmann on Cybersecurity
量子位
V
V2EX
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Proofpoint News Feed
I
Intezer
Schneier on Security
Schneier on Security
雷峰网
雷峰网
B
Blog RSS Feed
Jina AI
Jina AI
爱范儿
爱范儿
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
M
MIT News - Artificial intelligence
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
美团技术团队
博客园 - 【当耐特】

博客园 - riccc

微服务、分库分表、分布式事务管理、APM链路跟踪性能分析演示项目 - riccc - 博客园 SQL Server用错关联方式 事务信息系统-并发控制与恢复的理论, 算法与实践-计算模型, 并发控制部分 数据库系统 - 面向应用的方法 Data Modeling Technologies - ER, IE, Barker, IDEF1X, EXPRES-G, ORM 计划清单 声明:***本博客停止更新维护*** ANTLR SQL解析器代码 Hibernate Shards 数据的水平、垂直切割(三)- Hibernate Shards结构 Hibernate Shards 数据的水平、垂直切割(二)- Hibernate Shards基本演示 Hibernate Shards 数据的水平、垂直切割(一)- Hibernate测试环境 IKVM - 0.42.0.3 .NET平台上的Java实现 NVelocity 1.1 vs StringTemplate 3.2 IoC - StructureMap 2.6.1 AOP - PostSharp 2.0 AOP - AspectSharp 2.1.1.0 IoC - Castle Windsor - 扩展container 2.1 IoC - Castle Windsor 2.1 Mono.Cecil - 0.6
Castle NVelocity - 1.1 - riccc
riccc · 2010-04-02 · via 博客园 - riccc

VTL语法
注释
单行注释以##开始,多行注释以#*开始,以*#结束。注释的内容不会出现在输出中

属性

属性引用以$符号开始。属性可以是服务器端C#代码设置的,也可以在NVelocity模板中定义属性,比如下面语句在NVelocity模板中定义一个属性
#set (#msg="this variable is defined in NVelocity.")
NVelocity中定义的属性一般为字符串值,赋值时可以使用单引号将字符串值括起来,也可以使用双引号,他们的区别是:如果字符串值中有用到其他变量,使用单引号时该变量名字直接作为字符串的值处理,而使用双引号时该变量名字将使用属性的值进行替换(可以设置NVelocity关闭这个选项)
在模板中如果需要输出以$符号开始的文本(非变量),有2种处理方式。如果他不会作为属性赋值,则可以直接输出,因为NVelocity对没有赋值的属性,直接输出属性名字(包括$符号);如果他是一个已经赋值的属性,则需要在$符号前面添加一个转义用的反斜杠\符号
对于非字符串类型的属性,NVelocity调用属性的ToString()方法转换为字符串输出
对于对象类型的属性,可以使用类似$contact.Name方式,NVelocity目前的版本已经支持属性名称非大小写敏感

控制指令
条件指令:
NVelocity中的控制指令基本上就2个:条件指令和循环指令。NVelocity对宏的支持不太好
#if($score>1000) Expert #elseif($score>500) Senior #else Junior #endif
与Velocity不一样的地方:NVelocity不支持#{else}这个语法,#else、#endif指令必须与前后的内容空格分开

循环指令:
NVelocity的循环指令,每个指令必须单独占用一行,不能有注释、输出内容等
NVelocity对Velocity的循环指令做了扩展,加入了Fog Creek的Fancy Loops
基本语法如下:

#foreach($i in $items)

#each 

    (this is optional since its the default section)

    text which appears for each item

#before

    text which appears before each item

#after

    text which appears after each item

#between

    text which appears between each two items

#odd

    text which appears for every other item, including the first

#even

    text which appears for every other item, starting with the second

#nodata

    Content rendered if $items evaluated to null or empty

#beforeall

    text which appears before the loop, only if there are items

    matching condition

#afterall

    text which appears after the loop, only of there are items

    matching condition

#end
Fancy Loops指令非常实用,例如在StringTemplate中想要类似的效果就比较麻烦

其他还有#include、#parse、#stop指令,详细的语法参考VTL Reference

基本用法
下载Castle NVelocity项目,建一个测试用的web site,引用NVelocity.dll,引用的命名空间如下:

using System;

using System.Collections.Generic;

using System.Data;

using Commons.Collections;

using NVelocity;

using NVelocity.App;

using NVelocity.Runtime;

建立一个NVelocity模板,内容如下:

<div class="query-form">
    <table>
        <tr>
            <td>姓名:</td>
            <td><input type="text" id="txtQryName" class="text" value="$qryName" /></td>
            <td>地址:</td>
            <td><input type="text" id="txtQryAddress" class="text" value="$qryAddress" /></td>
            <td><input type="button" id="btnQuery" value="查询" /></td>
        </tr>
    </table>
</div>

<h2>Contact List</h2> <div class="contact-list"> #foreach($c in $contacts) #beforeall <table> <tr class="list-header"> <td>姓名</td> <td>邮箱</td> <td>地址</td> <td>会员等级</td> </tr> #odd <tr class="list-odd"> #even <tr class="list-even"> #each <td>$c.set_Name("$c.name - W") $c.get_Name()</td> <td><a href="mailto:$c.EMail">$c.EMail</a></td> <td>$c.Address</td> <td>#if($c.TotalOrderAmt>1000)钻卡会员 #elseif($c.TotalOrderAmt>200)金卡会员 #else Standard#end</td> #after </tr> #afterall </table> #nodata No contacts found! #end </div>

页面.cs代码如下:

public class Contact
{
    public string Name { get; set; }
    public string EMail { get; set; }
    public string Address { get; set; }
    public decimal TotalOrderAmt { get; set; }
}

protected void Page_Load(object sender, EventArgs e) { VelocityEngine engine = new VelocityEngine(); ExtendedProperties prop = new ExtendedProperties(); prop.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, Server.MapPath("./")); prop.AddProperty(RuntimeConstants.ENCODING_DEFAULT, "utf-8"); engine.Init(prop); Template template = engine.GetTemplate("contact-list.vm"); VelocityContext context = new VelocityContext(); context.Put("contacts", new List<Contact>() { new Contact() { Name="Richie Liu", TotalOrderAmt=180, EMail="RichieLiu-test@gmail.com", Address="上海徐汇区钦州路" }, new Contact() { Name="Kevin Zhang",TotalOrderAmt=0, EMail="KevinZhang-test@gmail.com", Address="苏州新区" }, new Contact() { Name="Eric Wong", TotalOrderAmt=626, EMail="EricWong-test@gmail.com", Address="厦门海沧" }, new Contact() { Name="RicCC", TotalOrderAmt=2080, EMail="RicCC-test@gmail.com", Address="上海徐汇区钦州路" } }); context.Put("qryName", "Ric"); context.Put("qryAddress", DateTime.Now);
template.Merge(context, this.Response.Output); }

则页面运行结果:
    
上面的代码中,演示了在NVelocity模板中调用对象的方法,比如$c.get_Name()通过getter方法读取属性值;$c.set_Name("$c.name - W")为每个contact的名字添加一个-W后缀
如果$contacts集合中没有记录,则只会输出No contacts found!文本,不会输出任何table信息,包括#beforeall、#afterall指令中的内容也不会输出

接下来测试一下#foreach指令能够支持的集合类型以及用法(只要支持IEnumarable接口的都可以使用#foreach指令)
NVelocity模板如下:

<br />
<h2>Item List - Array</h2>
<div>
#foreach($item in $items1)
#each
    $item
#between
    ,
#end
</div>

<br /> <h2>Item List - List</h2> <div> #foreach($item in $items2) #each $item.ToString("yyyy-MM-dd") #between , #end </div>
<br /> <h2>Item List - Dictionary</h2> <div> #foreach($item in $items3) #each { $item.Key - $item.Value } #between ,#end </div>
<br /> <h2>Item List - DataTable</h2> <div> #foreach($item in $items4.Rows) { $item.Key - $item.Value } #between , #end </div>

服务器端设置属性的代码如下:

context.Put("items1", new string[] { "AAA", "BBB", "CCC" });
context.Put("items2", new List<DateTime> { new DateTime(1979, 1, 1), new DateTime(2010, 4, 1) });

IDictionary<string, decimal> dic = new Dictionary<string, decimal>(); dic.Add("AAA", 111M); dic.Add("BBB", 222M); dic.Add("CCC", 333M); context.Put("items3", dic);
DataTable table = new DataTable(); table.Columns.Add(new DataColumn("Key", typeof(string))); table.Columns.Add(new DataColumn("Value", typeof(int))); DataRow row = table.NewRow(); row["Key"] = "item 1"; row["Value"] = 111; table.Rows.Add(row); row = table.NewRow(); row["Key"] = "item 2"; row["Value"] = 222; table.Rows.Add(row); context.Put("items4", table);

页面运行效果如下: