Groovy模板引擎介紹

版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文參考自Template engines,大部分代碼直接引用了文檔的內容。

模板引擎介紹

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

  • SimpleTemplateEngine - 基本的模板
  • StreamingTemplateEngine - 功能和 SimpleTemplateEngine相同,不過支持大於64k的模板
  • GStringTemplateEngine - 將模板保存爲可寫的閉包,在流式場景中很有用
  • XmlTemplateEngine - 輸出XML文件的模板引擎
  • MarkupTemplateEngine - 一個完整的、優化過的模板引擎,可以用於生成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的規範。

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{expression}和variable語法來插入數據。還提供了gsp:scriptletgsp: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程序的視圖層使用。不過我在實際用的時候發現一點問題,那就是Intellij IDEA沒有支持……這就比較蛋疼了,我好像在記事本里寫代碼一樣。這大概就是它最主要的缺點了吧。

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

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

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

模型數據是這樣的。

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文章的話,應該很容易猜出來哪些是方法、哪些是參數了。

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方法,這些方法主要在模板文件是動態的時候纔有用。

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') }  

使用模板引擎

使用方法和其他模板引擎差不多。都要創建引擎實例,然後傳入模板文件和數據。標記模板引擎還需要一個額外的配置對象。

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);  

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

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

國際化

我們可以爲每個模板文件創建不同區域的版本,這樣就可以讓程序可以實現國際化功能。例如,原始的文件是file.tpl,那麼法語版本的文件就是file_fr_FR.tpl,英語版本就是file_en_US.tpl。在創建模板配置對象的時候,我們可以傳遞一個Locale對象作爲默認區域使用。

強類型聲明

Groovy模板的類型是在運行時解析的,不過我們也可以手動聲明數據類型,這樣模板執行速度會更快。在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正常解析了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章