Groovy 与 DSL

一: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自身语法的特性,比如:

  1. 不需要 class定义,直接执行脚本
  2. Groovy语法的简洁
  3. Groovy提供了更多通俗易懂的方法
  4. 省略()和;等
  5. 等等

    Groovy自身不是 DSL Groovy官方已经发布了较多基于 Groovy书写的 DSL,比如 GANT GORMXMLBuilder HtmlBuilder等等。

 

三:我们的目标

     实现一种使用 Groovy语法书写、用于构建 HTML的(其实就是 HtmlBuilder)的简单 DSL,如下:

 

Java代码   收藏代码
  1. html {  
  2.     head {  
  3.         meta {  
  4.               
  5.         }  
  6.     }  
  7.     body {  
  8.         table (style:'margin:5px;') {  
  9.             tr ('class':'trClass', style:'padding:5px;') {  
  10.                 td {'Cell1'}  
  11.                 td {'Cell2'}  
  12.                 td {'Cell3'}  
  13.             }  
  14.         }  
  15.     }  
  16. }  

 

     这段代码比较容易让人懂,很容易让人将 HTML与之对应起来。具体怎么实现能够通过这一段 DSL代码输出原始的 HTML呢?主要基于 Groovy的以下几个特性:

 

  1. Groovy脚本,不用定义 class
  2. Groovy invokeMethod方法
  3. 方法可不书写()
  4. 语句末尾省略;分号
  5. 不书写 return

四:代码分析

 

Java代码   收藏代码
  1. meta {  
  2. }  

这段代码的含义为:调用 meta方法,参数为一个闭包,闭包不执行任何代码。

 

Java代码   收藏代码
  1. table (style:'margin:5px;') {  
  2. }  

这段代码的含义为:调用 table方法,第一个参数为 Map,第二个参数为闭包。

Java代码   收藏代码
  1. tr ('class':'trClass', style:'padding:5px;') {  
  2.                 td {'Cell1'}  
  3.                 td {'Cell2'}  
  4.                 td {'Cell3'}  
  5. }  

这段代码的含义为:

调用 tr方法,第一个参数为 Map,第二个参数为闭包。

闭包中,调用了 3  td方法,参数都为一个闭包;闭包中直接返回了一个字符串。

 

五:代码实现

    将代码解读了以后,再结合 invokeMethod就很容易实现了,具体代码如下:

Java代码   收藏代码
  1. def invokeMethod(String name, args) {  
  2.     print "<${name}"  
  3.     args.each { arg ->  
  4.         if (arg instanceof Map) {  
  5.             arg.each {  
  6.                 print " ${it.key} ='${it.value}' "  
  7.             }  
  8.         } else if (arg instanceof Closure) {  
  9.             print '>'  
  10.             arg.delegate = this  
  11.             def value = arg.call()  
  12.             if (value) {  
  13.                 print "${value}"  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18.     println "</${name}>"  
  19. }  
  20.   
  21. html {  
  22.     head {  
  23.         meta {  
  24.               
  25.         }  
  26.     }  
  27.     body {  
  28.         table (style:'margin:5px;') {  
  29.             tr ('class':'trClass', style:'padding:5px;') {  
  30.                 td {'Cell1'}  
  31.                 td {'Cell2'}  
  32.                 td {'Cell3'}  
  33.             }  
  34.         }  
  35.     }  
  36. }  

 

六:运行

Html代码   收藏代码
  1. <html><head><meta></meta>  
  2. </head>  
  3. <body><table style ='margin:5px;' ><tr class ='trClass'  style ='padding:5px;' ><td>Cell1</td>  
  4. <td>Cell2</td>  
  5. <td>Cell3</td>  
  6. </tr>  
  7. </table>  
  8. </body>  
  9. </html>  

 

七:结论

   基于Groovy自身的语法简洁和众多特性,实现一个专属的DSL还是蛮简单的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值