鷹翔宇空

          學(xué)習(xí)和生活

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks

          引自: http://www-128.ibm.com/developerworks/cn/java/j-pg04125/

          ?

          實(shí)戰(zhàn) Groovy: 用 Groovy 生成器作標(biāo)記

          拋開標(biāo)記語言的細(xì)節(jié),聚焦應(yīng)用程序的內(nèi)容

          developerWorks
          文檔選項(xiàng)
          將此頁作為電子郵件發(fā)送

          將此頁作為電子郵件發(fā)送

          未顯示需要 JavaScript 的文檔選項(xiàng)


          對(duì)此頁的評(píng)價(jià)

          幫助我們改進(jìn)這些內(nèi)容


          級(jí)別: 初級(jí)

          Andrew Glover , CTO, Vanward Technologies

          2005 年 4 月 12 日

          Groovy 生成器讓您能夠利用諸如 Swing 這樣的框架來模擬標(biāo)記語言(如 XML、HTML、Ant) 任務(wù)以及 GUI。它們對(duì)于快速原型化非常有用,并且正像 Andrew Glover 這個(gè)月在“實(shí)戰(zhàn) Groovy”專欄中向您展示的那樣,當(dāng)您馬上需要可消費(fèi)的標(biāo)記時(shí),它們是數(shù)據(jù)綁定框架的一種便利的替代方案。

          幾個(gè)月前,當(dāng)我最初撰寫有關(guān) 實(shí)戰(zhàn) Groovy: 用 Groovy 進(jìn)行 Ant 腳本編程 的文章時(shí),我提及了 Groovy 中的生成器 概念。在那篇文章里,我向您展示了,使用一個(gè)叫做 AntBuilder 的 Groovy 類,構(gòu)建富有表現(xiàn)力的 Ant 構(gòu)建文件是多么容易。本文中,我將深入 Groovy 生成器的世界,向您展示您還能用這些強(qiáng)大的類做些什么。

          用生成器進(jìn)行構(gòu)建

          Groovy 生成器讓您能夠利用諸如 Swing 這樣的框架來模擬標(biāo)記語言(如 XML、HTML、Ant) 任務(wù)以及 GUI。使用生成器,您可以迅速地創(chuàng)建復(fù)雜的標(biāo)記(如 XML),而無須理會(huì) XML 本身。

          生成器的范例非常簡單。生成器的實(shí)例的方法表示該標(biāo)記(如 HTML 中的 <body> 標(biāo)簽)的元素。方法的創(chuàng)建于閉包中的對(duì)象表示子節(jié)點(diǎn)(例如,<body> 標(biāo)簽中所包含的 <p> 標(biāo)簽)。

          為了便于您查看這一過程,我將創(chuàng)建一個(gè)簡單的生成器,以程序方式來表示一個(gè)具有清單 1 所示結(jié)構(gòu)的 XML 文檔。




          關(guān)于本系列文章

          在開發(fā)實(shí)踐中采用任何工具的關(guān)鍵是,了解何時(shí)使用這些工具,何時(shí)將其棄而不用。腳本語言可能是對(duì)工具包的一個(gè)功能強(qiáng)大的擴(kuò)充,但是只有在正確應(yīng)用于適當(dāng)?shù)沫h(huán)境時(shí)才是如此。總之,實(shí)戰(zhàn) Groovy系列文章旨在展示 Groovy 的實(shí)際使用,以及何時(shí)和如何成功應(yīng)用它。


          清單 1. 簡單 XML 結(jié)構(gòu)
          												
          														 <person>
             <name first="Megan" last="Smith">
               <age>32</age>
               <gender>female</gender>
             </name>
             <friends>
               <friend>Julie</friend>
               <friend>Joe</friend>
               <friend>Hannah</friend>
             </friends>
           </person>
          
          												
          										

          要表示這個(gè)結(jié)構(gòu)非常簡單。首先將 person 方法連接到生成器實(shí)例,現(xiàn)在它表示 XML 的根節(jié)點(diǎn),即 <person>。要?jiǎng)?chuàng)建子節(jié)點(diǎn),我創(chuàng)建一個(gè)閉包并聲明一個(gè)名叫 name 的新對(duì)象(它接收 map 形式的參數(shù)。順便說一下,這些參數(shù)是元素的屬性的基礎(chǔ)。

          接下來,在 name 對(duì)象中,將兩個(gè)附加對(duì)象連接到閉包,一個(gè)對(duì)象是 age,另一個(gè)是 gender,它們對(duì)應(yīng)于 <name> 的類似子元素。您明白其中的訣竅了么?確實(shí)很簡單。

          <friends> 元素是 <person> 的兄弟元素,于是我跳出這個(gè)閉包,聲明了一個(gè) friends 對(duì)象,當(dāng)然,還附加了一個(gè)集合了多個(gè) friend 元素的閉包,如清單 2 所示。


          清單 2. 生成器是如此的簡單
          												
          														import groovy.xml.*
          import java.io.*
          class XMLBuilder{
            
            static void main(args) {
            
              writer = new StringWriter()	 	
              builder = new MarkupBuilder(writer)
              friendnames = [ "Julie", "Joey", "Hannah"]
              
          	builder.person() {
                 name(first:"Megan", last:"Smith") {
                   age("33")
                   gender("female")
                 }
                 friends() {
                   for (e in friendnames) { friend(e) }
                 }
              }
              println writer.toString()
            }
          }
          
          												
          										

          如您所見,這里的 Groovy 表示非常優(yōu)雅,且易于映射到相應(yīng)的標(biāo)記表示。在底層,Groovy 顯然在處理煩人的標(biāo)記元素(如 < and >),使我們可以將更多精力放在內(nèi)容上,而不必過分在意結(jié)構(gòu)的細(xì)節(jié)。



          回頁首


          顯示 HTML

          生成器也可以有助于構(gòu)建 HTML,這在開發(fā) Groovlet 時(shí)可以派上用場。如同小菜一碟,假設(shè)我要?jiǎng)?chuàng)建一個(gè)如清單 3 所示的 HTML 頁面。


          清單 3. HTML 101
          												
          														 <html>
            <head>
             <title>Groov'n with Builders</title>
            </head>
            <body>
             <p>Welcome to Builders 101. As you can see this Groovlet is fairly simple.</p>
            </body>
           </html>
          
          												
          										

          我可以輕易地將它編碼在 Groovy 中,清單 4 所示。


          清單 4. HTML in Groovy 101
          												
          														import groovy.xml.*
          import java.io.*
          class HTMLBuilderExample{
            
            static void main(args) {
             writer = new StringWriter()	 	
             builder = new MarkupBuilder(writer)
            
             builder.html(){
               head(){
                 title("Groov'n with Builders"){}
               }
               body(){
                 p("Welcome to Builders 101. As you can see " +
                   "this Groovlet is fairly simple.") 
               }
             }
             println writer.toString()
          }
          
          												
          										

          來點(diǎn)有意思的,讓我們?cè)倏纯从蒙善鹘⒁粋€(gè)成熟的 GUI 有多么容易。前面我曾提到過,Groovy 的 SwingBuilder 使它能夠以一種極為簡單的方式構(gòu)造 GUI。您可以查閱清單 5 中 SwingBuilder 是如何工作的。


          清單 5. Groovy 中的 GUI 生成器真的很“GROOVY”(很“棒”)
          												
          														import java.awt.FlowLayout
          import javax.swing.*
          import groovy.swing.SwingBuilder
          class SwingExample{
            
            static void main(args) {
              swinger = new SwingBuilder()
              langs = ["Groovy", "Ruby", "Python", "Pnuts"]
            
          	gui = swinger.frame(title:'Swinging with Groovy!', size:[290,100]) {
                panel(layout:new FlowLayout()) {
                  panel(layout:new FlowLayout()) {
                    for (lang in langs) {
                      checkBox(text:lang)
                    }
                  }
                  button(text:'Groovy Button', actionPerformed:{ 
                    swinger.optionPane(message:'Indubitably Groovy!').createDialog(null, 'Zen Message').show()
                  })
                  button(text:'Groovy Quit', actionPerformed:{ System.exit(0)})
               }
             }
             gui.show()
             }
          }
          
          												
          										

          圖 1 顯示了上面的結(jié)果,還不錯(cuò)吧?


          圖 1. Groovy 中神奇的 GUI 編程

          可以想像,對(duì)于原型化,SwingBuilder 是一個(gè)多么強(qiáng)大的工具,不是么?



          回頁首


          一些事實(shí)

          這些例子雖然瑣碎,卻也有趣。我希望我能讓您明白,Groovy 的生成器可以讓您避免特定語言(如 XML)中的底層標(biāo)記。顯然,有時(shí)避免 XML 或 HTML 會(huì)更好,并且,那些標(biāo)記協(xié)助器(facilitator)對(duì) Java 平臺(tái)來說并不陌生。例如,我最喜歡的 XML 協(xié)助框架是 JiBX。

          使用 JiBX,您可以輕易地將 XML 結(jié)構(gòu)映射到對(duì)象模型,反之亦然。綁定是個(gè)強(qiáng)大的范例,有不計(jì)其數(shù)的類似工具擁有此功能,如 JAXB、 Castor 和 Zeus 等。

          綁定框架的惟一缺點(diǎn)是,它們恐怕 要耗費(fèi)不少時(shí)間。幸運(yùn)的是,您可以使用 Groovy 的生成器作為一個(gè)較簡單的 解決方案,這在某些情況下是有效的。



          回頁首


          用生成器進(jìn)行偽綁定

          假設(shè)有一個(gè)英文詞典的簡單數(shù)據(jù)庫。有一個(gè)表用于 word,另一個(gè)表用于 definition ,最后還有一個(gè)表用于 synonym。圖 2 是這個(gè)數(shù)據(jù)庫的簡單表示。


          圖 2. 詞典數(shù)據(jù)庫

          如您所見,這個(gè)數(shù)據(jù)庫非常直觀:worddefinitionsynonym 具有一對(duì)多的關(guān)系。

          詞典數(shù)據(jù)庫擁有一個(gè)消費(fèi)者,他在尋求一種表示數(shù)據(jù)庫內(nèi)容的關(guān)鍵方面的 XML 結(jié)構(gòu)。所尋求的 XML 結(jié)構(gòu)如清單 6 所示。


          清單 6. 可采用的詞典 XML
          												
          														<words>
            <word spelling="glib" partofspeech="adjective">
              <defintions>
                <defintion>Performed with a natural, offhand ease.</defintion>
                <defintion>Marked by ease and fluency of speech or writing that often suggests 
          	  or stems from insincerity, superficiality, or deceitfulness</defintion>
              </defintions>
              <synonyms>
                <synonym spelling="artful"/> 
                <synonym spelling="urbane"/> 
              </synonyms>
            </word>	
          </words>
          
          												
          										

          如果選擇使用 JiBX 這樣的綁定框架來解決這個(gè)問題,則很可能需要?jiǎng)?chuàng)建一些中間對(duì)象模型,以從關(guān)系模型到達(dá)最終的 XML 模型。然后必須將數(shù)據(jù)庫內(nèi)容讀取到對(duì)象模型中,并請(qǐng)求底層框架將其內(nèi)部的結(jié)構(gòu)編組為 XML 格式。

          這一過程內(nèi)含了將對(duì)象結(jié)構(gòu)映射到 XML 格式的步驟(使用所需的框架過程)。某些框架,如 JAXB,實(shí)際上是從 XML 和其他框架(如 JiBX )生成 Java 對(duì)象,允許您自定義自己的 Java 對(duì)象到 XML 格式的映射。總之,這都需要大量的工作。

          并且,這是一項(xiàng)宏偉的計(jì)劃。我并不提倡避免使用綁定框架。這里,我要聲明:我已經(jīng)預(yù)先警告過您。我計(jì)劃向您展示的是一個(gè)生成 XML 的便捷方式。

          可消費(fèi)的 XML 很簡單

          使用 Groovy 的 MarkupBuilder,結(jié)合新的數(shù)據(jù)庫訪問框架 GroovySql,您可以輕易地生成可消費(fèi)的 XML。您所要做的只是計(jì)算出所需的查詢,并將結(jié)果映射到生成器實(shí)例 —— 然后,您馬上就可以得到表示詞典數(shù)據(jù)庫內(nèi)容的 XML 文檔。

          讓我們逐步來了解這一過程。首先,創(chuàng)建一個(gè)生成器實(shí)例,在本例中是 MarkupBuilder,因?yàn)槟胍?XML。最外面的 XML 元素(也就是“根”)是 words,這樣就創(chuàng)建了一個(gè) words 方法。在閉包里,調(diào)用第一個(gè)查詢,并在迭代中將查詢結(jié)果映射到 word 子節(jié)點(diǎn)。

          接著,通過兩個(gè)新的查詢,創(chuàng)建 word 的兩個(gè)子節(jié)點(diǎn)。創(chuàng)建一個(gè) definitions 對(duì)象,并在迭代中映射它,接著用同樣的方法處理 synonyms


          清單 7. 用生成器集合所有元素
          												
          														import groovy.sql.Sql
          import groovy.xml.MarkupBuilder
          import java.io.File
          import java.io.StringWriter
          class WordsDbReader{
            static void main(args) {
              sql = Sql.newInstance("jdbc:mysql://localhost/words", 
                "words", "words", "org.gjt.mm.mysql.Driver")
              writer = new StringWriter()	 	
              builder = new MarkupBuilder(writer)
              builder.words() {
                sql.eachRow("select word_id, spelling, part_of_speech from word"){ row |
                  builder.word(spelling:row.spelling, partofspeech:row.part_of_speech){
                   
          		 builder.definitions(){
                      sql.eachRow("select definition from definition where word_id = ${row.word_id}"){ defrow |
                        builder.definition(defrow.definition)
                      }
                   }
                   
          		 builder.synonyms(){  		       		
                      sql.eachRow("select spelling from synonym where word_id = ${row.word_id}"){ synrow |
                        builder.synonym(synrow.spelling)
                      }		       					       		
                   }
                 }
                }
              }
             new File("dbouuput.xml").withPrintWriter{ pwriter |
                pwriter.println writer.toString()
             }
           }
          }
          
          												
          										

          結(jié)束語

          這里,我向您展示的綁定解決方案似乎簡單得讓人難以置信,特別是以 Java 純化論者的觀點(diǎn)看來更是如此。盡管該解決方案不比使用綁定框架(如 JABX 和 JiBX) 更好,但它確實(shí)更快一些 —— 而且,我主張使用這樣較簡單的方法。是不是我在簡單的 Java 代碼中做一些類似的事情?是的,但我敢肯定,某些時(shí)候我也不得不處理 XML。

          用 Groovy 生成器進(jìn)行開發(fā)的速度和簡易性,在調(diào)用標(biāo)記的時(shí)候可大顯神威。例如,就像在第二個(gè)例子里展示的那樣,我可以馬上加快數(shù)據(jù)庫的 XML 表示。對(duì)于原型化,或者當(dāng)需要以最少的開發(fā)時(shí)間和精力來產(chǎn)生可工作的解決方案時(shí),生成器也是一個(gè)不錯(cuò)的選擇。

          在下個(gè)月的實(shí)戰(zhàn) Groovy 中我會(huì)講些什么呢?哦,當(dāng)然是在 Java 語言中使用 Groovy!



          回頁首


          參考資料



          回頁首


          關(guān)于作者

          Andrew Glover 是 Vanward Technologies 的 CTO,該公司位于華盛頓特區(qū)的大都會(huì)地區(qū),公司的專業(yè)領(lǐng)域是自動(dòng)化測試工具和框架的構(gòu)造,該框架可以減少軟件 bug 數(shù)量,縮短集成和測試的時(shí)間,提高代碼的整體穩(wěn)定性。他是 Java Testing Patterns一書的合著者(Wiley,2004 年 9 月)。

          posted on 2006-02-09 14:51 TrampEagle 閱讀(370) 評(píng)論(0)  編輯  收藏 所屬分類: java
          主站蜘蛛池模板: 鲁甸县| 台北市| 黄浦区| 五原县| 中江县| 博湖县| 聂拉木县| 佛教| 湾仔区| 南丹县| 海盐县| 滨海县| 买车| 博爱县| 柳河县| 安岳县| 洪泽县| 高邑县| 汉川市| 芮城县| 宁阳县| 灵石县| 赤壁市| 清水县| 玉田县| 盘锦市| 嵊泗县| 阳江市| 华亭县| 龙胜| 吴桥县| 讷河市| 柘荣县| 钟祥市| 洪泽县| 阿拉善右旗| 饶阳县| 新宁县| 溧阳市| 安顺市| 贵溪市|