Groovy模板引擎

本文參考自Template engines记罚,大部分代碼直接引用了文檔的內容墅诡。

模板引擎介紹

Groovy語言包含了一個模板引擎功能,可以生成各種類型的格式化文件桐智,非常方便末早。模板引擎有下面幾個,它們都實現(xiàn)了Template接口说庭。

  • SimpleTemplateEngine - 基本的模板
  • StreamingTemplateEngine - 功能和 SimpleTemplateEngine相同然磷,不過支持大于64k的模板
  • GStringTemplateEngine - 將模板保存為可寫的閉包,在流式場景中很有用
  • XmlTemplateEngine - 輸出XML文件的模板引擎
  • MarkupTemplateEngine - 一個完整的口渔、優(yōu)化過的模板引擎样屠,可以用于生成HTML等模板

SimpleTemplateEngine

這是最賤的模板引擎, 使用起來也非常簡單缺脉。直接看Groovy文檔的例子吧痪欲。可以看到它的模板語法類似JSP標簽和EL表達式攻礼。

def text = 'Dear "$firstname $lastname",\nSo nice to meet you in <% print city %>.\nSee you in ${month},\n${signed}'

def binding = ["firstname":"Sam", "lastname":"Pullara", "city":"San Francisco", "month":"December", "signed":"Groovy-Dev"]

def engine = new groovy.text.SimpleTemplateEngine()
def template = engine.createTemplate(text).make(binding)

def result = 'Dear "Sam Pullara",\nSo nice to meet you in San Francisco.\nSee you in December,\nGroovy-Dev'

StreamingTemplateEngine

它和SimpleTemplateEngine類似业踢,只不過能處理比較大的文本。它使用<% %>礁扮、<%= %>和GString語法知举。下面的例子同樣來自Groovy文檔。

def text = '''\
Dear <% out.print firstname %> ${lastname},

We <% if (accepted) out.print 'are pleased' else out.print 'regret' %> \
to inform you that your paper entitled
'$title' was ${ accepted ? 'accepted' : 'rejected' }.

The conference committee.'''

def template = new groovy.text.StreamingTemplateEngine().createTemplate(text)

def binding = [
    firstname : "Grace",
    lastname  : "Hopper",
    accepted  : true,
    title     : 'Groovy for COBOL programmers'
]

String response = template.make(binding)

assert response == '''Dear Grace Hopper,

We are pleased to inform you that your paper entitled
'Groovy for COBOL programmers' was accepted.

The conference committee.'''

GStringTemplateEngine

首先我們先將模板保存為文件太伊。注意在模板中沒有使用print方法雇锡,而是使用out,這樣符合GString的規(guī)范僚焦。

Dear "$firstname $lastname",
So nice to meet you in <% out << (city == "New York" ? "\\"The Big Apple\\"" : city) %>.
See you in ${month},
${signed}

然后讀取模板锰提,并使用給定的字符串替換模板。

def f = new File('test.template')
def engine = new groovy.text.GStringTemplateEngine()
def template = engine.createTemplate(f).make(binding)
println template.toString()

XmlTemplateEngine

XmlTemplateEngine用于生成XML模板。它提供了標準的${expression}$variable語法來插入數(shù)據(jù)立肘。還提供了<gsp:scriptlet><gsp:expression>用來插入代碼段和表達式边坤。<>"'這幾個符號會在處理模板的時候轉義。gsp: tags命名空間的標簽會在模板生成的時候移除谅年,其他命名空間則不會移除茧痒。

下面是Groovy文檔的例子。

def binding = [firstname: 'Jochen', lastname: 'Theodorou', nickname: 'blackdrag', salutation: 'Dear']
def engine = new groovy.text.XmlTemplateEngine()
def text = '''\
    <document xmlns:gsp='http://groovy.codehaus.org/2005/gsp' xmlns:foo='baz' type='letter'>
        <gsp:scriptlet>def greeting = "${salutation}est"</gsp:scriptlet>
        <gsp:expression>greeting</gsp:expression>
        <foo:to>$firstname "$nickname" $lastname</foo:to>
        How are you today?
    </document>
'''
def template = engine.createTemplate(text).make(binding)
println template.toString()

生成的結果如下融蹂。

<document type='letter'>
  Dearest
  <foo:to xmlns:foo='baz'>
    Jochen "blackdrag" Theodorou
  </foo:to>
  How are you today?
</document>

MarkupTemplateEngine

簡介

終于說到重點了旺订。這其實才是本篇文章想要說的重點內容。在官方文檔中殿较,前面所有內容才占了所有內容的四分之一耸峭。剩下的內容都在這里。

Groovy標記模板引擎的功能很強淋纲,完全可以作為一個WEB程序的視圖層使用劳闹。不過我在實際用的時候發(fā)現(xiàn)一點問題,那就是Intellij IDEA沒有支持……這就比較蛋疼了洽瞬,我好像在記事本里寫代碼一樣本涕。這大概就是它最主要的缺點了吧。

這個標記模板引擎主要用來生成類XML的模板伙窃,類似HTML等等菩颖。但是也可以用來生成所有類型的文檔。前面那些模板都是基于字符串的为障。而這個模板是基于Groovy DSL的(學過Gradle就明白了晦闰,它們長得很像)。

先來看看直觀的例子吧鳍怨。假設有下面的模板呻右。

xmlDeclaration()
cars {
   cars.each {
       car(make: it.make, model: it.model)
   }
}

模型數(shù)據(jù)是這樣的。

model = [cars: [new Car(make: 'Peugeot', model: '508'), new Car(make: 'Toyota', model: 'Prius')]]

最后生成的文件類似這樣鞋喇。

<?xml version='1.0'?>
<cars><car make='Peugeot' model='508'/><car make='Toyota' model='Prius'/></cars>

Groovy標記模板引擎提供的功能有強類型的模型檢查声滥、代碼片和導入、國際化等幾個重要功能侦香。

代碼格式和方法

標記模板其實是合法的Groovy代碼落塑。下面這個代碼中其實有很多方法和閉包,看看你能認出幾個罐韩。其實看了這么多Groovy文章的話憾赁,應該很容易猜出來哪些是方法、哪些是參數(shù)了散吵。

yieldUnescaped '<!DOCTYPE html>'                                                    
html(lang:'en') {                                                                   
    head {                                                                          
        meta('http-equiv':'"Content-Type" content="text/html; charset=utf-8"')      
        title('My page')                                                            
    }                                                                               
    body {                                                                          
        p('This is an example of HTML contents')                                    
    }                                                                               
}  

廢話就不說了龙考。說說常用的方法吧膘壶。

  • yieldUnescaped方法會直接輸出給定的語句,不轉義其中的字符洲愤。
  • yield方法和上面相反,會轉義特殊字符顷锰。
  • head這些HTML標簽方法會生成對應的標簽柬赐。
  • xmlDeclaration()方法會生成一個標準的XML文檔頭。
  • comment方法生成HTML注釋官紫。
  • newLine生成一個新行肛宋。

包含

模板中還可以包含其他模板。下面是三種包含方式束世,分別包含另一個模板酝陈,不需要轉義的文本或者是需要轉義的文本。

include template: 'other_template.tpl'
include unescaped: 'raw.txt'
include escaped: 'to_be_escaped.txt'

還有幾個等價的Groovy方法毁涉,這些方法主要在模板文件是動態(tài)的時候才有用沉帮。

includeGroovy(<name>) 
includeEscaped(<name>)
includeUnescaped(<name>)

布局

我們可以編寫布局文件。布局文件和其它Groovy模板文件的后綴名都是tpl贫堰。我一開始不知道穆壕,結果找不到視圖文件,花了不少時間其屏。例如編寫下面這樣一個文件喇勋。

html {
    head {
        title(title)                
    }
    body {
        bodyContents()              
    }
}

然后將頁面寫為下面這樣。Groovy模板引擎會將布局文件和實際布局結合偎行,生成最終的布局川背。

layout 'layout-main.tpl',                                   
    title: 'Layout example',                                
    bodyContents: contents { p('This is the body') }  

使用模板引擎

使用方法和其他模板引擎差不多。都要創(chuàng)建引擎實例蛤袒,然后傳入模板文件和數(shù)據(jù)熄云。標記模板引擎還需要一個額外的配置對象。

TemplateConfiguration config = new TemplateConfiguration();         
MarkupTemplateEngine engine = new MarkupTemplateEngine(config);     
Template template = engine.createTemplate("p('test template')");    
Map<String, Object> model = new HashMap<>();                        
Writable output = template.make(model);                             
output.writeTo(writer);  

默認情況下生成的模板是部分行的汗盘,適合生產環(huán)境但是不適合人類閱讀皱碘。我們可以修改配置來讓結果更可讀。下面的配置打開了縮進和分行隐孽。其他配置請查閱相應文檔癌椿。

config.setAutoNewLine(true);
config.setAutoIndent(true);

國際化

我們可以為每個模板文件創(chuàng)建不同區(qū)域的版本,這樣就可以讓程序可以實現(xiàn)國際化功能菱阵。例如踢俄,原始的文件是file.tpl,那么法語版本的文件就是file_fr_FR.tpl晴及,英語版本就是file_en_US.tpl都办。在創(chuàng)建模板配置對象的時候,我們可以傳遞一個Locale對象作為默認區(qū)域使用。

強類型聲明

Groovy模板的類型是在運行時解析的琳钉,不過我們也可以手動聲明數(shù)據(jù)類型势木,這樣模板執(zhí)行速度會更快。在modelTypes中將使用到的模型聲明出即可歌懒。

modelTypes = {                          
    List<Page> pages                    
}

pages.each { page ->
    p("Page title: $page.title")
    p(page.text)
}

Spring集成

Spring對Groovy標記模板提供了支持啦桌。只要類路徑存在Groovy相關類,就可以配置使用Groovy標記模板及皂。

首先先添加Groovy的依賴甫男。下面是Gradle的依賴配置。

compile 'org.codehaus.groovy:groovy-all:2.4.9'

然后在Spring配置文件中添加下面的配置验烧。

<!--Groovy模板引擎-->
<mvc:view-resolvers>
    <mvc:groovy/>

</mvc:view-resolvers>
<!--Groovy模板引擎配置-->
<mvc:groovy-configurer auto-indent="true"
                       cache-templates="false"
                       resource-loader-path="/WEB-INF/templates"/>

之后板驳,在配置的模板路徑下編寫*.tpl格式的模板文件,就可以讓Spring正常解析了碍拆。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末若治,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子倔监,更是在濱河造成了極大的恐慌直砂,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浩习,死亡現(xiàn)場離奇詭異静暂,居然都是意外死亡,警方通過查閱死者的電腦和手機谱秽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門洽蛀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疟赊,你說我怎么就攤上這事郊供。” “怎么了近哟?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵驮审,是天一觀的道長。 經常有香客問我吉执,道長疯淫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任戳玫,我火速辦了婚禮熙掺,結果婚禮上,老公的妹妹穿的比我還像新娘咕宿。我一直安慰自己币绩,他們只是感情好蜡秽,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缆镣,像睡著了一般芽突。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上董瞻,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天诉瓦,我揣著相機與錄音,去河邊找鬼力细。 笑死,一個胖子當著我的面吹牛固额,可吹牛的內容都是我干的眠蚂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼斗躏,長吁一口氣:“原來是場噩夢啊……” “哼逝慧!你這毒婦竟也來了?” 一聲冷哼從身側響起啄糙,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤笛臣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后隧饼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沈堡,經...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年燕雁,在試婚紗的時候發(fā)現(xiàn)自己被綠了诞丽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡拐格,死狀恐怖僧免,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情捏浊,我是刑警寧澤懂衩,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站金踪,受9級特大地震影響浊洞,放射性物質發(fā)生泄漏。R本人自食惡果不足惜热康,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一沛申、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姐军,春花似錦铁材、人聲如沸尖淘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽村生。三九已至,卻和暖如春饼丘,著一層夾襖步出監(jiān)牢的瞬間趁桃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工肄鸽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卫病,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓典徘,卻偏偏與公主長得像蟀苛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逮诲,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內容