Groovy 與 DSL

一:DSL 概念html

指的是用於一個特定領域的語言(功能領域、業務領域)。在這個給出的概念中有 3個重點:數據庫

只用於一個特定領域,而非全部通用領域,好比 Java / C++就是用於通用領域,而不可被稱爲 DSL,一樣也不可把 Groovy稱爲 DSL。編程

語言,必須通過編寫後纔可發揮它的功能。好比:五線譜編寫後成曲譜; ANT編寫用於編譯; SVN命令編寫後可對資源庫進行操做; Shell編程; SQL編程; PL-SQL編程等等。閉包

忽略具體的運行環境(媒介),能夠是紙、 XML文件、命令行、 Shell、數據庫等。編程語言

二:Groovy對 DSL的支持gradle

Groovy不是 DSL,而是通用的編程語言。但 Groovy卻對編寫出一個全新的 DSL提供了良好的支持,這些支持都來自於 Groovy自身語法的特性,好比:ui

不須要 class定義,直接執行腳本this

Groovy語法的簡潔spa

Groovy提供了更多通俗易懂的方法命令行

省略()和;等

等等

Groovy自身不是 DSL。 Groovy官方已經發布了較多基於 Groovy書寫的 DSL,好比 GANT, GORM, XMLBuilder, HtmlBuilder等等。

三:咱們的目標

實現一種使用 Groovy語法書寫、用於構建 HTML的(其實就是 HtmlBuilder)的簡單 DSL,以下:

html {  
    head {  
        meta {  
              
        }  
    }  
    body {  
        table (style:'margin:5px;') {  
            tr ('class':'trClass', style:'padding:5px;') { td {'Cell1'} td {'Cell2'} td {'Cell3'} } } } }

這段代碼比較容易讓人懂,很容易讓人將 HTML與之對應起來。具體怎麼實現可以經過這一段 DSL代碼輸出原始的 HTML呢?主要基於 Groovy的如下幾個特性:

Groovy腳本,不用定義 class

Groovy的 invokeMethod方法

方法可不書寫()

語句末尾省略;分號

不書寫 return

四:代碼分析

meta {  
}  
//這段代碼的含義爲:調用 meta方法,參數爲一個閉包,閉包不執行任何代碼。

table (style:'margin:5px;') { } //這段代碼的含義爲:調用 table方法,第一個參數爲 Map,第二個參數爲閉包。 tr ('class':'trClass', style:'padding:5px;') { td {'Cell1'} td {'Cell2'} td {'Cell3'} } //這段代碼的含義爲: //調用 tr方法,第一個參數爲 Map,第二個參數爲閉包。 //閉包中,調用了 3 個 td方法,參數都爲一個閉包;閉包中直接返回了一個字符串。

五:代碼實現

將代碼解讀了之後,再結合 invokeMethod就很容易實現了,具體代碼以下:

def invokeMethod(String name, args) {  
    print "<${name}" args.each { arg -> if (arg instanceof Map) { arg.each { print " ${it.key} ='${it.value}' " } } else if (arg instanceof Closure) { print '>' arg.delegate = this def value = arg.call() if (value) { print "${value}" } } } println "</${name}>" } html { head { meta { } } body { table (style:'margin:5px;') { tr ('class':'trClass', style:'padding:5px;') { td {'Cell1'} td {'Cell2'} td {'Cell3'} } } } }

六:運行結果

<html><head><meta></meta> </head> <body><table style ='margin:5px;' > <tr class ='trClass' style ='padding:5px;' > <td>Cell1</td> <td>Cell2</td> <td>Cell3</td> </tr> </table> </body> </html>

七:結論基於Groovy自身的語法簡潔和衆多特性,實現一個專屬的DSL仍是蠻簡單的。

相關文章
相關標籤/搜索