普通Replace模板做法
很多人在做郵件模板、短信模板的時候,都是使用特殊標識的字符串進行占位,然后在后台代碼中進行Replace字符串,如果遇到表格形式的內容,則需要在后台進行遍歷數據集合,進行字符串的拼接,繼而Replace模板中的占位符,示例代碼就像是這樣:
<html> <head> <title>[title]</title> </head> <body> <h1>[title]</h1> <table> <tr><td>姓名</td><td>專業</td></tr> [TableContent] </table> </body> </html>
string templateStr = "xxxxx"; //這里讀取模板,從數據庫或者從文件中 StringBuilder sb=new StringBuilder(); sb.Append("<tr><td>小明</td><td>計算機專業</td></tr>"); sb.Append("<tr><td>小紅</td><td>美術專業</td></tr>"); templateStr = templateStr.Replace("[title]", "給你一個標題").Replace("[TableContent]", sb.ToString()); return templateStr;
Nvelocity介紹
Nvelocity就像很多的模板引擎一樣,以特定的語法編寫好模板,然后為模板提供數據源,最終就會渲染生成出HTML,優點是模板與代碼分離,很多的Nvelocity博文都是以html文件作為模板來進行的,但是我發現,也可以使用字符串模板來使用,這樣你的模板就不必要存在html文件中了,存儲在數據庫中也可以,這應該更適合於大多數的項目。
Nvelocity下載地址:http://www.castleproject.org/download/ 找到NVELOCITY這一項進行下載即可。
一個簡單示例揭開Nvelocity的面紗
新建一個Application,在項目中添加Nvelocity的引用,然后添加新建項,選擇一般處理程序,命名為basic.ashx,在ProcessRequest方法里填入下面代碼
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; //創建一個模板引擎 VelocityEngine vltEngine = new VelocityEngine(); //文件型模板,還可以是 assembly ,則使用資源文件 vltEngine.SetProperty(RuntimeConstants.RESOURCE_LOADER, "file"); //模板存放目錄 vltEngine.SetProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, System.Web.Hosting.HostingEnvironment.MapPath("/template"));//模板文件所在的文件夾 vltEngine.Init(); //定義一個模板上下文 VelocityContext vltContext = new VelocityContext(); //傳入模板所需要的參數 vltContext.Put("Title", "標題"); //設置參數,在模板中可以通過$Title來引用 vltContext.Put("Body", "內容"); //設置參數,在模板中可以通過$Body來引用 vltContext.Put("Date", DateTime.Now); //設置參數,在模板中可以通過$Date來引用 //獲取我們剛才所定義的模板,上面已設置模板目錄 Template vltTemplate = vltEngine.GetTemplate("basic.html"); System.IO.StringWriter vltWriter = new System.IO.StringWriter(); //根據模板的上下文,將模板生成的內容寫進剛才定義的字符串輸出流中 vltTemplate.Merge(vltContext, vltWriter); string html = vltWriter.GetStringBuilder().ToString(); context.Response.Write(html); }
然后在項目里,添加一個文件夾並且命名為template,作為存放模板的目錄,這與上面代碼里設置的模板目錄要對應一致,然后添加新建項,選擇HTML頁,命名為basic.html,輸入以下代碼
<html> <head> <title></title> </head> <body> <p>$Title</p> <p>$Date</p> <p>$Body</p> </body> </html>
F5運行,看看效果
直接運行HTML肯定只能看到模板的效果而已,我們工作的原理是,在一般處理程序ashx中讀取模板來生成HTML,並且輸出給客戶端瀏覽器,所以我們要訪問的應該是一般處理程序ashx。
成功了,並且值都是代碼中我們設置的值。
以字符串為模板源,不必新建HTML頁
很多時候,我們的模板都是存放在數據庫中的,而不是像上例那樣以html文件的形式存放,Nvelocity也為我們提供這種形式的模板源,直接上代碼就行了。
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; //字符串模板源,這里就是你的郵件模板等等的字符串 string templateStr = "$Title,$Body,$Date"; //創建一個模板引擎 VelocityEngine vltEngine = new VelocityEngine(); //文件型模板,還可以是 assembly ,則使用資源文件 vltEngine.SetProperty(RuntimeConstants.RESOURCE_LOADER, "file"); vltEngine.Init(); //定義一個模板上下文 VelocityContext vltContext = new VelocityContext(); //傳入模板所需要的參數 vltContext.Put("Title", "標題"); //設置參數,在模板中可以通過$Title來引用 vltContext.Put("Body", "內容"); //設置參數,在模板中可以通過$Body來引用 vltContext.Put("Date", DateTime.Now); //設置參數,在模板中可以通過$Date來引用 //定義一個字符串輸出流 StringWriter vltWriter = new StringWriter(); //輸出字符串流中的數據 vltEngine.Evaluate(vltContext, vltWriter, null, templateStr); context.Response.Write(vltWriter.GetStringBuilder().ToString()); }
Nvelocity模板語法
關於后台代碼基本就是那樣了,對於Nvelocity的重點應該是如何去編寫適合需求的模板,上面的例子Put的時候,都是以字符串為例的,那么,假如Put一個對象、集合呢?Nvelocity都可以輕松解決,為了演示,下面的例子只貼出重點部分的代碼。
1、基本用法
vltContext.Put("Title", "標題"); //設置參數,在模板中可以通過$Title來引用
vltContext.Put("Body", "內容"); //設置參數,在模板中可以通過$Body來引用
vltContext.Put("Date", DateTime.Now); //設置參數,在模板中可以通過$Date來引用
<html> <body> <p>$Title</p> <p>$Date</p> <p>$Body</p> </body> </html>
2、NVelocity中輸出對象的屬性
如果只能像上面那樣子的基本用法的話,那簡直太渣了,還不如直接IO讀取模版直接Replace,下面演示一些更加高級的用法,直接Put一個對象,然后在模版中引用其屬性,那樣子就更加碉堡了,Nvelocity還可以支持對象的屬性是對象的調用方法,引用的時候就好比$p.Son.Name
//定義一個模板上下文 VelocityContext vltContext = new VelocityContext(); Person p = new Person() { Name = "dotnetgeek", Age = 10 }; //傳入模板所需要的參數 vltContext.Put("p", p); //設置參數為對象,在模板中可以通過$p.Name 來引用
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> 姓名:$p.Name,年齡:$p.Age </body> </html>
3、NVelocity對象的索引
//定義一個模板上下文 VelocityContext vltContext = new VelocityContext(); Dictionary<string, string> dic = new Dictionary<string, string>(); dic["dudu"] = "博客園"; dic["Jimmy"] = "softcomz"; //傳入模板所需要的參數 vltContext.Put("dic", dic); //設置參數為對象,在模板中可以通過$dic.dudu 來引用
<html>
<body>
$dic.dudu
$dic.Jimmy
</body>
</html>
4、NVelocity中的ForEach遍歷和If判斷
VelocityContext vltContext = new VelocityContext(); List<string> lstSite = new List<string>(){"博客園","微博"}; //傳入模板所需要的參數 vltContext.Put("lst", lstSite);
<html> <body> <ul> #foreach($s in $lst) <li>$s</li> #end </ul> #if(1==1) 一等於一 #else 一不等於一 #end </body> </html>
在前台的模版中,有關后台代碼的編寫,如果以#開頭,比如#foreach 、#if(condition),因為沒有大括號的約束,所以結束時以#end為標識,ForEach和If還可以嵌套使用,就像平時我們寫后台代碼的那樣,只是語法稍稍有點不同而已,有了這樣的高級特性,這對於編寫模版來說就能做很多的事情了。
5、NVelocity中Parse和Include
#parse("head.html") <p>$body</p> #include("footer.html")
顧名思義,#include就是在模版中在將其他模版包括進來,就好比網站的頭部,尾部,廣告模版等等,這些內容都是相同的時候,就可以做成一個單獨的模版供各處引用。
#parse的用法跟#include相類似,如果將上面的代碼改成#parse之后,效果是一樣的,#parse的特殊功能在於,它可以解析Nvelocity元素,比如,body.html 模版使用Nvelocity變量$body ,如果使用#parse引用head.html和footer.html兩個模版,則在head.html、footer.html模版中繼續可以使用$body這個變量,而#include做不到,並且相關的Nvelocity元素(#foreach、#if)也不起效果,只能原樣輸出,所以#parse > #inclued
6、前台聲明變量使用#set
在前台的Nvelocity代碼中,根據需要,我們可以聲明一個供前台使用的參數,這樣就免得后台代碼再次傳遞過來了,對於一些簡單邏輯,我們可以這樣實現
#if(1<10) #set($nextnum=1+1+1+1)
//下面的邏輯就可以使用nextnum這個變量了。
#end
建議使用匿名類來進行代碼封裝
上面提過,對於Nvelocity我們的重點應該是放在編寫適合需求的模板,后台的代碼基本上是一次封裝,多次調用即可了,只需要把要Put的對象做成一個可變參數,剩余的代碼進行一個封裝就行了,那么如何更好的調用,我建議使用匿名類,因為隨着模板的編寫,我們可能需要傳遞多種、多個數據,使用匿名類的好處就是,類屬性自定義而不用像自定義一個類型那樣,每次增加數據屬性就得去修改一下類型,這樣顯得很優雅很隨性簡便。
var model = new { ID = "dudu", PersonLaoPo = new Person() { Name = "冰冰", Age = 100 } }; vltContext.Put("Model", model);
Demo下載