Groovy 与 DSL(转)

基于原贴,用Markdown语法美化了一下。
原贴:https://www.cnblogs.com/xingzc/p/6347673.html

一:DSL 概念

指的是用于一个特定领域的语言(功能领域、业务领域)。在这个给出的概念中有 3个重点:

  1. 只用于一个特定领域,而非所有通用领域,比如 Java / C++就是用于通用领域,而不可被称为 DSL,同样也不可把 Groovy称为 DSL。
  2. 语言,必须经过编写后才可发挥它的功能。比如:五线谱编写后成乐谱; ANT编写用于编译; SVN命令编写后可对资源库进行操作; Shell编程; SQL编程; PL-SQL编程等等。
  3. 忽略具体的运行环境(媒介),可以是纸、 XML文件、命令行、 Shell、数据库等。

二:Groovy对 DSL的支持

Groovy不是 DSL,而是通用的编程语言。但 Groovy却对编写出一个全新的 DSL提供了良好的支持,这些支持都来自于 Groovy自身语法的特性,比如:

  • 不需要 class定义,直接执行脚本
  • Groovy语法的简洁
  • 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还是蛮简单的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335