<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0' gd:etag='W/&quot;D0cFR3Y-cSp7ImA9WhJaF00.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687</id><updated>2012-10-08T07:03:36.859-07:00</updated><category term='sap'/><category term='xml'/><category term='Grails'/><category term='GORM'/><category term='jQuery'/><category term='java'/><category term='jco'/><category term='Groovy'/><title>Aska 的 IT 臥龍崗。我本是臥龍崗散淡的人。</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default?redirect=false&amp;v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry gd:etag='W/&quot;D0cFR3Y8fip7ImA9WhJaF00.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-1701268198012882345</id><published>2012-10-07T14:59:00.003-07:00</published><updated>2012-10-08T07:03:36.876-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-10-08T07:03:36.876-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='GORM'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title>Grails 如何取得 hibernate 的 session ?</title><content type='html'>有的時候還是忍不住想要下native sql ，在 grails 中要如何取得 &amp;nbsp;session 呢?&lt;br /&gt;
答案簡單到不行…&lt;br /&gt;
&lt;br /&gt;
首先在controller 宣告一個&amp;nbsp;&amp;nbsp;&lt;span style="background-color: #eeeeee;"&gt;def sessionFactory&lt;/span&gt;。&lt;br /&gt;
&lt;br /&gt;
在你要執行的方法中，寫&lt;br /&gt;
&lt;br /&gt;
&lt;span style="background-color: #f3f3f3;"&gt;def ss = sessionFactory.getCurrentSession()&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
這個 ss 就是hibernate 的session ! 等下，那怎麼取得&amp;nbsp;&lt;span style="background-color: #f3f3f3;"&gt;sessionFactory&lt;/span&gt;&lt;span style="background-color: white;"&gt; ? 別忘了Grails 內建Spring的注入功能，該注的他都幫你注入進去了。&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="background-color: #f3f3f3;"&gt;def ret = ss.createSQLQuery("select * from post").list()&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: #f3f3f3;"&gt;println ret.get(0)[0]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
這種方法回傳的就是 List&amp;lt;Object[]&amp;gt; !&lt;br /&gt;
Grails 幫我們做掉太多事了! 邊學邊拍桌子啊 !&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-1701268198012882345?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/1701268198012882345/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/10/grails-hibernate-session.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/1701268198012882345?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/1701268198012882345?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/10/grails-hibernate-session.html' title='Grails 如何取得 hibernate 的 session ?'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;D0QDSHo_eip7ImA9WhJaEEQ.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-5409547851009328783</id><published>2012-10-01T05:38:00.001-07:00</published><updated>2012-10-01T05:42:59.442-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-10-01T05:42:59.442-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='GORM'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title>Grails 的ORM 關聯(一) belongsTo, hasMany</title><content type='html'>我們直接舉1對1，或是1對多的例子。&lt;br /&gt;
&lt;br /&gt;
一對多來說，一個作者可以發表多篇文章。&lt;br /&gt;
那這個關聯我們要從哪邊開始加？我們可以先在「文章」（多）中先加 belongsTo。&lt;br /&gt;
文章「屬於」作者。這個應該沒有疑問。&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
class Post {
　　String content
　　Date dateCreated
　　static constraints = {
　　　content(blank: false)

　　}
　　&lt;b style="background-color: #fce5cd;"&gt;static belongsTo = [ user : User ]&lt;/b&gt;
}

&lt;/code&gt;&lt;/pre&gt;
最後的　static belongsTo = [ user : User ]　當然是我們注意的重點。
&lt;br /&gt;
這個&amp;nbsp;[ user : User ] 其實是一個map，不過一個小寫的user ，一個大寫的 User有何用處?&lt;br /&gt;
這個user是給我們用做參考關聯的。透過這個寫法，Post 也可以反著查詢 User了。&lt;br /&gt;
&lt;br /&gt;
例如有一個畫面是閱讀某人寫的文章，最上面需要出現那個人的id。因為我們在這裡已經建立好倒回去關聯 User 時的變數名稱 「user」，所以只要 post.user.userId 便很快的可以得到我們要的結果。&lt;br /&gt;
&lt;br /&gt;
你可能也看過&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;&lt;b style="background-color: #f3f3f3;"&gt;static belongsTo = User &lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;
的寫法，如果這樣寫的話，post 就不能反過來查到對應的 user了。如果沒有必要從 Post 反查 User 時，這樣寫當然有一點效能上的優勢。&lt;br /&gt;
&lt;br /&gt;
belongsTo 還有要注意的一點，既然都說自己「屬於」別人了，所以當 User 從資料庫上被幹掉的同時，Post 也沒有任何存在的必要了。這個就是「屬於」的觀念。&lt;br /&gt;
當然在 User 這個類別上，也要記得加上&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;&lt;span style="background-color: #f3f3f3;"&gt;static hasMany = [ post : Post ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
如此一來關聯就正式接上了。接上之後有很多預設的神奇招式，在下一章會講到。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-5409547851009328783?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/5409547851009328783/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/10/grails-orm-belongsto.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/5409547851009328783?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/5409547851009328783?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/10/grails-orm-belongsto.html' title='Grails 的ORM 關聯(一) belongsTo, hasMany'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;CEMNSH8-eip7ImA9WhJaEEQ.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-5843692876126256739</id><published>2012-10-01T04:53:00.003-07:00</published><updated>2012-10-01T04:54:59.152-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-10-01T04:54:59.152-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title>Grails 中 Domain class 如何自訂驗證</title><content type='html'>Groovy 彈性的語法，總是讓人有一點不習慣，但其實抓住幾個原則就行。&lt;br /&gt;
先來看這個自訂驗證的範例。&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
  static constraints = &lt;b style="background-color: white;"&gt;&lt;span style="color: blue;"&gt;{&lt;/span&gt;&lt;/b&gt;
     userId (unique:true , size : 3..20)
     &lt;b&gt;password(&lt;/b&gt;
       nullable:true , 
       size : 6..8 ,
       validator :&lt;b&gt;&lt;span style="color: blue;"&gt;&lt;span style="background-color: white;"&gt;{&lt;/span&gt; password , user -&amp;gt;
          return password != user.userId
       &lt;span style="background-color: white;"&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/b&gt;     
     &lt;b&gt;)&lt;/b&gt;
     homepage(nullable:true , url : true)
   
  &lt;b&gt;&lt;span style="background-color: white; color: blue;"&gt;}&lt;/span&gt;&lt;/b&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;這個例子要達到的目的就是，使用者的密碼不要和帳號一樣即可。最大的限制式本身就是一個閉包。一般的驗證常用的就是 nullable , size 啊等等的。它有一點像 Java 後來加入的動態數量參數。所以你可以想到什麼就臨時加什麼 ( 當然缺點就是編譯時期無法知道是否正確 )。&lt;/li&gt;
&lt;li&gt;我們主要看的是在 password裡的「自訂驗證」，這個時候要加 validator : value。在 value 的部份，我們傳入一個閉包，這邊我用藍色框起來。從&lt;u&gt;key :value&lt;/u&gt; -&amp;gt;&amp;nbsp;&lt;u&gt;validator : value&lt;/u&gt; -&amp;gt;&amp;nbsp;&lt;u&gt;validator : 閉包&lt;/u&gt;。這樣就不會覺得 { &amp;nbsp; } 的出現很突兀了。&lt;/li&gt;
&lt;li&gt;這個validator 所用的閉包，可以接受二個參數。password 當然就是使用者傳進來的參數囉。第二個參數是user 物件，這是方便你做比較用的。簡單來說，閉包的參數就是二個，一個是password ，一個是user 物件。若你不需要用到user 物件，那只要指名 password -&amp;gt; 即可。&lt;/li&gt;
&lt;li&gt;後面要回傳true or false，所以你要告訴他怎樣是成功，怎樣驗證是失敗。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-5843692876126256739?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/5843692876126256739/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/10/grails-domain-class.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/5843692876126256739?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/5843692876126256739?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/10/grails-domain-class.html' title='Grails 中 Domain class 如何自訂驗證'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;CEMAQng9fCp7ImA9WhJaEEQ.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-141742642150007557</id><published>2012-09-30T13:22:00.000-07:00</published><updated>2012-10-01T04:54:03.664-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-10-01T04:54:03.664-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='Grails'/><title>Grails 2.x 整合測試要注意的地方</title><content type='html'>&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;2.x 版的整合測試 ( integration test ) 要注意的幾個地方&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;class UsersIntegrationTests extends GroovyTestCase  記得要extends 這個類別，不然無法啟動orm。&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;在塞資料到資料庫時，要記得「&lt;span style="color: red;"&gt;所有的屬性 nullable 預設為 false&lt;/span&gt;」，也就是所有的值你都要塞入，如果不想要的話要自己明確指定 nullable:true&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;在整合測試一直找不到原因的時候，例如當初&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;def user  = new Users( userId : 'joe')&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;assertNotNull user.save(flush:true)&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;最後一行一直出錯，錯誤訊息很模糊，一直不明其因。&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;在整合測試中，也請記得&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;println user.errors&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;很快的你就會看到原因了。印出來之後才發現我的屬性沒有全塞。&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;很快的再 Google 一下，才發現 2.x 預設的nullable屬性改了。&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;總之，希望有需要幫助的人剛好看到。&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;* 在gsp/jsp 丟到controller的東西是 "blank" 喔! 沒填值的話，等於是丟空字串，並不是null。&lt;/span&gt;&lt;br /&gt;
&lt;span style="color: white; font-family: Arial, Helvetica, sans-serif;"&gt;&amp;nbsp;Grails 2.x integration test save not working failed gorm&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-141742642150007557?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/141742642150007557/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/grails-2x.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/141742642150007557?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/141742642150007557?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/grails-2x.html' title='Grails 2.x 整合測試要注意的地方'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;CkQEQH87fSp7ImA9WhJaEEw.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-4305943211645486843</id><published>2012-09-30T06:01:00.005-07:00</published><updated>2012-09-30T06:05:01.105-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-30T06:05:01.105-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>Groovy與XML的相遇(三) : 如何找到節點</title><content type='html'>這一次就不寫 Java Code了，因為用傳統的寫法會發瘋。&lt;br /&gt;
&lt;br /&gt;
一樣，以剛剛那個xml為範例&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code" style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 826px;"&gt;&lt;code&gt;&amp;lt;root&amp;gt;
  &amp;lt;star age='22' blood='A'&amp;gt;布萊德彼特1&amp;lt;/star&amp;gt;
  &amp;lt;star age='26' blood='C'&amp;gt;小勞勃道尼&amp;lt;/star&amp;gt;
  &amp;lt;star age='24' blood='B'&amp;gt;基努李維&amp;lt;/star&amp;gt;
&amp;lt;/root&amp;gt; &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
(明明他們就沒那麼年輕…)

&lt;br /&gt;
&lt;br /&gt;
問題1: &amp;nbsp;找到年紀小於25歲的男星，我只要他們的名字&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code" style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 826px;"&gt;&lt;code&gt;println roots.star.find{  &lt;u&gt;it.@age &amp;lt;=25&lt;/u&gt; }.text() &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
下底線又用了閉包傳入。很簡單吧! 可是執行失敗說!&lt;br /&gt;
因為xml讀進來都是字串啊，Groovy沒有人工智慧。&lt;br /&gt;
好，那怎麼辦…? 你如果有從我第一篇開始看，你應該記得轉型吧。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code" style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 826px;"&gt;&lt;code&gt;println roots.star.find{  &lt;u&gt;it.@age as int &amp;lt;=25 &lt;/u&gt;}.text() &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
你很快樂的按下去，不過結果還是錯的，你不要把Groovy當神好嗎。
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code" style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 826px;"&gt;&lt;code&gt;println roots.star.find{  &lt;u&gt;(it.@age as int) &amp;lt;=25&lt;/u&gt; }.text() &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
加個括號就行了。是那裡面的東西要轉成 int ，後面再來比條件。&lt;br /&gt;
問題1的解法，一行結束! 不過剛剛符合條件的男星有二個耶 ?&lt;br /&gt;
find 只會傳出第一個 match 的。&lt;br /&gt;
findAll 會傳出都符合條件的。於是我們再試一次&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code" style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 826px;"&gt;&lt;code&gt;List list = roots.star.findAll{  &lt;u&gt;(it.@age as int)  &amp;lt;=25&lt;/u&gt; } as List
 &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
沒錯，還順便轉了型，裡面裝好了&amp;nbsp;groovy.util.Node。&lt;br /&gt;
List&amp;lt;groovy.util.Node&amp;gt; 啦。&lt;br /&gt;
&lt;br /&gt;
問題2 : 把這些明星的年紀由小到大排序，呃，我要大於23歲的。然後裝成 List&amp;lt;Integer&amp;gt;。&lt;br /&gt;
&lt;br /&gt;
當然以Groovy來說一定要秒殺解決的。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code" style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 826px;"&gt;&lt;code&gt;List list2 = (roots.star.@age.findAll{ &lt;u&gt;(it as int ) &amp;gt;=23&lt;/u&gt; } as List).sort()&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
我把這一行一個一個說明;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;取得root下的所有明星節點，但是我要他們的age而已，這時候已經是單純 age 的字串集合了。&lt;/li&gt;
&lt;li&gt;從這個結果中，幫我找 age 集合中年紀大於23 歲的，並轉型成 list。&lt;/li&gt;
&lt;li&gt;然後再排序。&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
是不是很方便呢? 其它的進階 xml 密技，就給你自己去研究了 !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-4305943211645486843?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/4305943211645486843/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovyxml_30.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/4305943211645486843?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/4305943211645486843?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovyxml_30.html' title='Groovy與XML的相遇(三) : 如何找到節點'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;AkYAQn48fCp7ImA9WhJaEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-649605237505463493</id><published>2012-09-30T05:06:00.000-07:00</published><updated>2012-09-30T05:29:03.074-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-30T05:29:03.074-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>Groovy與XML的相遇(二) : 解析文件</title><content type='html'>按照傳統，還是先來一段 Java code, 31行&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
import org.xml.sax.SAXException;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.IOException;

public class ParseXml {
  public static void main(String[] args) {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse("src/languages.xml");

      //print the "type" attribute
      Element langs = doc.getDocumentElement();
      System.out.println("type = " + langs.getAttribute("type"));

      //print the "language" elements
      NodeList list = langs.getElementsByTagName("language");
      for(int i = 0 ; i &amp;lt; list.getLength();i++) {
        Element language = (Element) list.item(i);
        System.out.println(language.getTextContent());
      }
    }catch(ParserConfigurationException pce) {
      pce.printStackTrace();
    }catch(SAXException se) {
      se.printStackTrace();
    }catch(IOException ioe) {
      ioe.printStackTrace();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
我不針對上面抄來的程式做修正了，反正大約都是一層的xml簡單文件而已。下面是 Groovy 的寫法:&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
def roots = new XmlParser().parse("D:\\test.xml")
roots.star.each{ &amp;nbsp; 
   println "age="+it.attribute("age") +" " + &amp;nbsp;it.text() 
}

&lt;/code&gt;&lt;/pre&gt;
處理的是這份文件
&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
&amp;lt;root&amp;gt;
  &amp;lt;star age='22' blood='A'&amp;gt;布萊德彼特1&amp;lt;/star&amp;gt;
  &amp;lt;star age='26' blood='C'&amp;gt;小勞勃道尼&amp;lt;/star&amp;gt;
  &amp;lt;star age='24' blood='B'&amp;gt;基努李維&amp;lt;/star&amp;gt;
&amp;lt;/root&amp;gt; 

&lt;/code&gt;&lt;/pre&gt;
你應該已經知道 it 是預設的，如果你的閉包參數只有一個，那麼it 就是指這個物件。
唯一要注意的就是，如果要取 tag 裡的文字是用 text()，要取參數就是 it.attribute("名稱")。&lt;br /&gt;
&lt;br /&gt;
( 取參數也可以用 it.@age ，如果你開始習慣之後，就可以改成Groovy提供的做法。 &amp;nbsp;)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;roots.star.each&lt;/b&gt;&amp;nbsp;這種語法或許 Java 的程序員還不是很習慣，但其實jQuery 裡也大量使用這種觀念啊。
&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
$("#talbe1 tr)".each({

});
&lt;/code&gt;&lt;/pre&gt;
是否你覺得似曾相識呢? 我把它換行一下。

&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
$("#talbe1 tr)".each(  &lt;b&gt;{這裡就是一個活生生的閉包啊}&lt;/b&gt;   );
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
再注意一次相同性，都是把閉包 {  } 丟到方法each 中做參數。
在這裡閉包就像是一個沒名字的方法。&lt;br /&gt;
&lt;br /&gt;
你還是有一點意見對吧…&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
roots.star.each{ &amp;nbsp; 
   println "age="+it.attribute("age") +" " + &amp;nbsp;it.text() 
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
你說明明就有一點不同，和jQuery不同啊，少了圓括號與最後的分號。&lt;br /&gt;
那我們改一下再來跑一次。

&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
roots.star.each({     
    println "age=" + it.@age +" " +  it.text()   
});
&lt;/code&gt;&lt;/pre&gt;
我連分號都加了，這樣你沒話說了吧，還是可以跑啊。 why!!&lt;br /&gt;
為何在Groovy 不用加 (  ) 呢? 這是Groovy 提供的一種簡潔式的寫法。好啦，我直接整理給你看三種不同寫法，都可以跑。
&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
roots.star.each({     
     
});
roots.star.each(){     
     
};
roots.star.each{     
    
};
&lt;/code&gt;&lt;/pre&gt;
這三種都是一樣的意思。我很快的總結一下&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;真正的寫法是如此，閉包是each的參數。&amp;nbsp;&lt;/li&gt;
&lt;li&gt;為了好看，閉包可以放在each()的後面，因為它太長了嘛!&amp;nbsp;&lt;/li&gt;
&lt;li&gt;如果each只收一個閉包做為參數，那 ( ) 就可以省了，它是2 的再精簡寫法。&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
再感覺一下… Groovy 是不是沒那麼奇怪了呢?
是不是常覺得…如果jQuery的寫法可以用在 Java 多好? 
如果有這種感覺的話，你才是真的是個程序員!
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-649605237505463493?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/649605237505463493/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovyxml.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/649605237505463493?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/649605237505463493?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovyxml.html' title='Groovy與XML的相遇(二) : 解析文件'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;AkQFRX4-cSp7ImA9WhJaEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-6096120430596520482</id><published>2012-09-30T04:27:00.000-07:00</published><updated>2012-09-30T05:31:54.059-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-30T05:31:54.059-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>Groovy  與 XML 的相遇(一) : MarkupBuilder + XmlSlurper</title><content type='html'>用Groovy 來產生 xml 再簡單不過了。雖然以前的 dom4j也是用物件的方式操作，但你要做的功夫相當的多。
先貼Java要怎麼寫…大約51行
&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;

public class CreateXml {
  public static void main(String[] args) {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.newDocument();

      Element root = doc.createElement("root");      
      doc.appendChild(root);

      Element star1 = doc.createElement("star");
      Text text1 = doc.createTextNode("布萊德彼特");
      star1.appendChild(text1);
      root.appendChild(star1);

      Element star2 = doc.createElement("star");
      Text text2 = doc.createTextNode("小勞勃道尼");
      star2.appendChild(text2);
      langs.appendChild(star2);

      Element star3 = doc.createElement("star");
      Text text3 = doc.createTextNode("基努李維");
      star3.appendChild(text3);
      langs.appendChild(star3);

      // Output the XML
      TransformerFactory tf = TransformerFactory.newInstance();
      Transformer transformer = tf.newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      StringWriter sw = new StringWriter();
      StreamResult sr = new StreamResult(sw);
      DOMSource source = new DOMSource(doc);
      transformer.transform(source, sr);
      String xmlString = sw.toString();
      System.out.println(xmlString);
    }catch(ParserConfigurationException pce) {
      pce.printStackTrace();
    } catch (TransformerConfigurationException e) {
      e.printStackTrace();
    } catch (TransformerException e) {
      e.printStackTrace();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
雖然非常容易理解，一個一個物件生成，但這麼單純的事，要花51行來寫，覺得你快要死了嗎? (況且他們的屬性我還沒有加進去哩……)
來一點輕鬆的吧。先寫了一個第一版，15行，很棒了吧??

&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
import groovy.xml.MarkupBuilder
import groovy.util.XmlSlurper
def file = new File("d:\\test.xml")
def objs = [
    [ age: 22, name: "布萊德彼特", blood: "A" ],
    [ age: 26, name: "小勞勃道尼", blood: "C" ],
    [ age: 24, name: "基努李維", blood: "B" ] ]
def b = new MarkupBuilder(new FileWriter(file))
b.root {
    objs.each { o -&amp;gt;
        star(age: o.age , blood:o.blood ,  o.name) {          
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
如果不要先把資料弄成集合 ( 雖然這樣比較容易看的懂 )，要寫的行數更少…

&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
def xml = new groovy.xml.MarkupBuilder(new FileWriter("d:\\test.xml"))
xml.root(){
  star(age: 22, blood: "A" , "布萊德彼特")
  star(age: 26, blood: "C" , "小勞勃道尼")
  star(age: 24, blood: "B" , "基努李維")
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
對，你沒看錯，就是6行。
除了行數變少之外，易讀性完全破表。 root 並不是一個死的方法，你將它改成stars，那麼產出的xml的根節點就叫做stars了。裡面所有的東西都能改，只要你結構掌握住了，xml 某一個節點要加新的屬性，易如反掌! 維護程式的人，你覺得他看上面的51行容易理解，還是下面的6行呢?&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;我們都知道重構的重要。若只是為了把原來就繁複的語法歸類而重構，那為何不一開始就精簡語法?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
這樣精簡的xml 語法，很大的功勞一樣是用閉包做的。程式人員只要專心在資料面，如何產生xml 的部份並非你的價值所在。除非你是開發 xml parser 的人，否則不要沉醉在自己高深的50行程式中。這裡面並沒有價值。再一次強調，就像醫生的價值在於醫好別人的病，不在於你會用幾種手術刀。若你可以空手就取出腫瘤，30秒結束回家吃飯，沒有病人會想抱怨的。


&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-6096120430596520482?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/6096120430596520482/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy-xml-markupbuilder-xmlslurper.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/6096120430596520482?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/6096120430596520482?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy-xml-markupbuilder-xmlslurper.html' title='Groovy  與 XML 的相遇(一) : MarkupBuilder + XmlSlurper'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;CEYBSXg5cSp7ImA9WhJaEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-3668440294144772093</id><published>2012-09-30T03:44:00.000-07:00</published><updated>2012-09-30T03:49:18.629-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-30T03:49:18.629-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>再談 Closure</title><content type='html'>上一篇講了，閉包是物件，不是方法，雖然使用上真的很像，這裡我們直接做證明…&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
  Closure comparator = { String a, String b -&amp;gt;
    a.compareToIgnoreCase(b)
  }
&lt;/code&gt;&lt;/pre&gt;
這樣很明白了吧，Closure的確是物件。差別在這個物件把自己當參數傳入某個方法後，這個方法會執行 Closure裡的行為。
當然在宣告的時候和傳統的「方法」不同，你要用 {   } 括起來，而且要寫 = 。
參數也不是方法一樣的宣告方式，不過概念是一樣的。
只要能接受語法後，就把它想成「動態的方法」就好了。
在書上的例子寫到

&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;

Closure comparator = { String a, String b -&amp;gt;
   a.compareToIgnoreCase(b)
}
List fruit = [ "apple", "Orange", "Avocado", "pear", "cherry" ]
fruit.sort(comparator)
println "Sorted fruit: ${fruit}"
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
這是一種寫法。先定義好有名有姓的閉包，當然 sort 也要接受這樣的閉包，不然你也是白寫的。
能夠變的地方在裡面實作的「比較方式」而已。

若還記得我們上篇文章，那是一種更直接寫的寫法。就像暱名的方法一樣。&lt;br /&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
 rpt_list.sort{o1,o2-&amp;gt;
    o1.total&amp;lt;=&amp;gt;o2.total
 }
&lt;/code&gt;&lt;/pre&gt;
 後面還會很大量的使用 Closure，所以目前暫時還不習慣也是無所謂的。 
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-3668440294144772093?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/3668440294144772093/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/closure.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/3668440294144772093?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/3668440294144772093?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/closure.html' title='再談 Closure'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;C08NRXs7cSp7ImA9WhJaEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-8908960726914700962</id><published>2012-09-29T14:04:00.002-07:00</published><updated>2012-09-30T03:44:54.509-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-30T03:44:54.509-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>Groovy 的一些好用語法(二) &lt;&lt; , 動態屬性 , collect , sort , </title><content type='html'>Groovy 是一種動態語言，可以輕易的將方法加到原來死板的 Java 類別中，這樣可以帶來很多好處，有時候太有彈性，甚至用起來有一點頭暈腦脹，所以先整理一下一些好用的方法。&lt;br /&gt;
&lt;br /&gt;
先來講 &amp;lt;&amp;lt; 。&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
List rpt_list = new ArrayList()
rpt_list &lt;span style="color: red;"&gt;&lt;b&gt;&amp;lt;&amp;lt;&lt;/b&gt;&lt;/span&gt; new Report(name:"as1" , m1:10 , m2:20 , total:30)
rpt_list &amp;lt;&amp;lt; new Report(name:"as2" , m1:40 , m2:40 , total:80)
rpt_list &amp;lt;&amp;lt; new Report(name:"as3" , m1:20 , m2:30 , total:50)
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&amp;lt;&amp;lt; 看起來很奇怪，但說起來也蠻好理解的，就是「塞過去」。
看箭頭的方向也知道，我要把右邊的塞到左邊。這個是 Java 沒有的語法。 你要是看起來很不習慣，一樣還是可以用 add ，這是 Groovy 的好處，你把他想成加強版的 Java 即可。
&lt;br /&gt;
&lt;br /&gt;
new Report 右邊的東西，是把屬性像 map 一樣傳進去。冒號的左邊是key右邊是value。還蠻容易理解的吧。&lt;br /&gt;
&lt;br /&gt;
這邊有一個有趣的地方。一般來說 Java 要動態呼叫一個方法或是屬性，有一點麻煩，也就是說我們「執行時期」才知道要呼叫誰的話，在 Java 是比較不直觀的方式處理的。再一次強調，我的觀點仍然認為，&lt;b&gt;程式的價值不在這些轉換上，所以務必要很容易做到&lt;/b&gt;。&lt;br /&gt;
&lt;br /&gt;
既然你可以把 map 當建構子傳入，那你可能會想到他是怎麼動態去mapping。&lt;br /&gt;
假設你要自己寫也不難，在 Groovy 來說只要寫&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;def dynamic_prop="total"

assert rpt_list[0]."${dynamic_prop}" == rpt_list[0]."total"
assert rpt_list[0]."total" == rpt_list[0].total
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
下面二個斷言都會是 true。相信你已經知道 ${ } 是像jsp 裡的變數，Groovy可放在字串中。&lt;br /&gt;
所以&amp;nbsp;&lt;span style="background-color: #eeeeee; font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px;"&gt;rpt_list[0]."${dynamic_prop}" &amp;nbsp;=&amp;gt; 會變成&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #eeeeee; font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px;"&gt;rpt_list[0]."total"&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: #eeeeee; font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px;"&gt;&lt;/span&gt;

&lt;br /&gt;
&lt;br /&gt;
而造成了可以簡單的動態呼叫的效果。相對於 Java 直接又容易理解。&lt;br /&gt;
&lt;br /&gt;
好了你囉嗦了這麼久，該說 collect 了吧。我們已經準備好剛剛的 List 了&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;List rpt_list = new ArrayList()
rpt_list &lt;span style="color: red;"&gt;&lt;b&gt;&amp;lt;&amp;lt;&lt;/b&gt;&lt;/span&gt; new Report(name:"as1" , m1:10 , m2:20 , total:30)
rpt_list &amp;lt;&amp;lt; new Report(name:"as2" , m1:40 , m2:40 , total:80)
rpt_list &amp;lt;&amp;lt; new Report(name:"as3" , m1:20 , m2:30 , total:50)&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
再來你 GSP/JSP 的頁面，老闆要你最上面要先列出一個一個總和。&lt;br /&gt;
聰明的你應該想到上一集的招式了&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;List rpt_total_list = rpt_list*.getTotal()&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
事情有這麼簡單當然最好，但是老闆改口說，業務要看的是 / 1000 的單位啦，不然值太大。&lt;br /&gt;
你抓了抓頭，這樣 「星點」好像不能用了，其實還有更棒的招，就是collect，一行。&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;List rpt_total_list = rpt_list.collect&lt;span style="color: red;"&gt;&lt;b&gt;{&lt;/b&gt;&lt;/span&gt; &lt;u&gt;it.total/1000&lt;/u&gt; &lt;span style="color: red;"&gt;&lt;b&gt;}&lt;/b&gt;&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
我紅色標起來的是 Closure，大陸翻閉包，很難聽，就還是叫 Closure好了。&lt;br /&gt;
這樣說，閉包是一個物件，這個物件裡要寫一些邏輯，包起來當參數餵給 collect。&lt;br /&gt;
collect 裡頭，Groovy 自己幫你實做了，你要餵它的就是閉包 ( 好吧…叫閉包也行 )&lt;br /&gt;
collect 收到閉包後他做了什麼事 ?&lt;br /&gt;
其實 collect 在上例被呼叫了三次，因為rpt_list 裡有三個物件。&lt;br /&gt;
這邊依序取這三個物件的 total 後除 1000 ，然後add 到List 中，有多少加多少，加到完之後結束，把 List 傳出來這樣。&lt;br /&gt;
如果用傳統的 Java 來寫，又要容易閱讀的話 :&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;private List&amp;lt;Report&amp;gt; getTotalList(){
  List rpt_total_list = new ArrayList();
  for(Report r : rpt_list){
     rpt_total_list.add(r.getTotal);
  }
  return rpt_total_list ;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;//煩死了…一行Groovy比七行Java&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
閉包使用起來像一個方法，只是不用再獨立寫出來。Groovy 提供了很多對 Collection 的瘋狂技巧。再下來我們講sort。

想到要排序剛剛的sort就很頭痛，因為在 Java 來說，你得這樣寫。你要實作compare來完成這個需求，剛剛的名言又要再講一次，這種東西沒有價值，越好寫越快。價值在客戶要用什麼排序，不是在你怎麼寫出這段程式。

&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;public void sortPeopleByGivenName(List&lt;person&gt; personList) {
  Collections.sort(personList, new Comparator&lt;person&gt;() {
  public int compare(Person p1, Person p2) {
  return p1.getFamilyName().compareTo(p2.getFamilyName());
  }
  });
}
//很煩吧…&lt;/person&gt;&lt;/person&gt;&lt;/code&gt;&lt;/pre&gt;
用 Groovy 的話

&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;def sortIt(list, property) {
    list.sort { p1, p2 -&amp;gt; 
    p1."${property}" &amp;lt;=&amp;gt; p2."${property}" 
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
長的有一點奇怪，不過你呼叫 sortIt ( rpt_list , "total") 就可以得到你想要的結果了。 上面講過了，那個${}會整個被替換成你丟入的參數。你也注意到了 sort 本身就接受閉包，所以不如改成

&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;rpt_list.sort{o1,o2-&amp;gt;
    o1.total &lt;b&gt;&amp;lt;=&amp;gt;&lt;/b&gt; o2.total
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&amp;lt;=&amp;gt; 是啥啦 !
它就是

&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;
public int compare(int i1, int i2) {
 if (i1 == i2) return 0;
 else if (i1 &amp;lt; i2) return -1;
 else return 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
的簡寫啦 ! 所以在閉包裡如果比的是數字，除非你的比法和人家不同，否則 &amp;lt;=&amp;gt; 就行了!
這樣子 sort 你開心了嗎 ? 
今天講的就是 collect 與 sort
最後，其實 sort 還可以加條件，剛剛都白寫了 ! 
沒錯，Groovy的寫法真的太有彈性了，你還可以寫成
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;rpt_list.sort{ it.getTotal() } 
&lt;/code&gt;&lt;/pre&gt;
是不是很瘋狂呢? 叫你「按照裡面每一個物件的total 給我排序!」
如果你要排的是數字，最後一個方案就是你要的! 一行搞定。&lt;br /&gt;
&lt;br /&gt;
想哭嗎? 很正常。&lt;br /&gt;
如果不是單純的排序，你有一些奇怪規則的，留給你自己，在閉包裡動動腦筋囉!




&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-8908960726914700962?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/8908960726914700962/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy-collect-sort.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/8908960726914700962?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/8908960726914700962?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy-collect-sort.html' title='Groovy 的一些好用語法(二) &lt;&lt; , 動態屬性 , collect , sort , '/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;AkECRHk8cSp7ImA9WhJbGU8.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-7129082078577309524</id><published>2012-09-29T07:22:00.004-07:00</published><updated>2012-09-29T07:24:25.779-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-29T07:24:25.779-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>Groovy 的轉型</title><content type='html'>Groovy 的轉型寫為 as .&lt;br /&gt;
為什麼 Java 已經有轉型了，Groovy 還要發明一個 ? 舉個例子&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;String s = "this,is,a,book"
String[] arr = s.split(",");
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
你這個陣列用一用之後，突然後面的邏輯變了，你需要再動態 add 一些元素到這個已經拆開的陣列中，你也知道陣列在 Java 是不能隨意改變大小的，所以你只能再寫一些程式，把這個陣子轉成 List 後再處理。&lt;br /&gt;
我網路上隨便查了一些寫法 :&lt;br /&gt;
&lt;br /&gt;
1.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;List myList = new ArrayList();
String[] myStringArray = new String[] {"Java", "is", "Cool"};

Collections.addAll(myList, myStringArray);
&lt;/code&gt;&lt;/pre&gt;
2.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;String&amp;gt;(words.length);  
for (String s : words) {  
    list.add(s);  
}  
&lt;/code&gt;&lt;/pre&gt;
3.
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;List&amp;lt;String&amp;gt; ret = Arrays.asList( 裡面放字串陣列) 
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
好，無論怎樣，都只是在表達一件事而已，而且這些事對真正的程式邏輯來說毫不重要，不是商業邏輯的一部份。在 Groovy 來說仍舊是一行解決。&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;String s = "this,is,a,book"
def ret = s.split(",") as List
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
( 當然第一行是字串陣列不算啦 )

&lt;br /&gt;
這樣的好處很多! 而且中間甚至可以加上型態轉換，例如我們上一集的例子&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;def id_array = list*.getId() as Integer[]
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
我們假設 list 裡是一堆 Book ，而且他的id 是字串型態，我後面的程式需要他的 id 以數字的方式，包在整數陣列裡面。&lt;br /&gt;
&lt;br /&gt;
現在你看的懂了，在第一個方法呼叫後，得到的是List&amp;lt;String&amp;gt; ，但是我們要的其實是整數陣列 ( 對不起你的同事就是要整數陣列 ) ，你打幾個字便已輕舟過萬重山。&lt;br /&gt;
&lt;br /&gt;
如果你的同事突然發瘋，他決定還是List&amp;lt;Integer&amp;gt; 好了，那你就把 Integer[] 槓掉改成 List 就收工。&lt;br /&gt;
&lt;br /&gt;
請記住，程式的重點都是在解決一個問題，中間轉型或是換集合物件都沒有價值。這些沒有價值的事，就是要快速處理，敏捷開發，也要有敏捷的語言搭配才可以的 !&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-7129082078577309524?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/7129082078577309524/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy_29.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/7129082078577309524?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/7129082078577309524?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy_29.html' title='Groovy 的轉型'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;DUUDRH4_fCp7ImA9WhJbGU8.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-321691874765881314</id><published>2012-09-29T07:01:00.000-07:00</published><updated>2012-09-29T07:01:15.044-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-29T07:01:15.044-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='Groovy'/><title>Groovy 的一些好用語法(一)  *.</title><content type='html'>&amp;nbsp;Groovy 可以和Java語法混用，這一點真的是很有趣的事。&lt;br /&gt;
在很不熟Groovy的時候，甚至可以把 Java 的寫法套進來。但是久了之後就會發現，Java 在一件簡單的事上，往往要很重覆的不斷寫上一樣的東西。&lt;br /&gt;
&lt;br /&gt;
有些人會不屑的回應說，只是語法上的甜頭，不足掛齒。&lt;br /&gt;
其實這只看到表面。語法上的簡化、行數減少這是事實，不能否認，但好處為何?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;行數少，bug 就少。100行出錯的機率一定比10行來的高。&lt;/li&gt;
&lt;li&gt;行數少，程式的「自我描述性」就高。在 Java 中的五行，其實是在說一件事，但因為這5行會消耗你閱讀上的力氣，當行數越來越多的時候，你會很難抓住程式本身的重點。行數少，程式可以集中力氣在「表達」上，也就是易讀性會大大提升。&lt;/li&gt;
&lt;li&gt;等下的例子會十分明顯。&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
假設我們需要得到全部的「書」，然後把他的 id 傳到 jsp 供應用…不管你程式寫幾行，或用任何的程式語言，中文來說就是這二件事，以傳統的Java 來說:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;List&amp;lt;Book&amp;gt; book = session.createQuery("from Book").list(); 
//do something....
List&amp;lt;Integer&amp;gt; list_id = new ArrayList();
for(Book b : book){
   list_id.add(b.getId());
}
request.setAttribute("id_list",list_id);
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
這個是我們每天在寫程式的時候做的事，雖然很囉嗦但是久了也習慣了。&lt;br /&gt;
Groovy 怎麼處理?&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;def book = Book.list()
//do something
["id_list", book*.getId() ]
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
啥?&lt;br /&gt;
對，就是你眼睛看到的。&lt;br /&gt;
*. 是什麼 ? 其實望文生義，就是「在這個集合裡的所有物件，都都呼叫這個方法，得到的值紀錄起來用List傳出來」。&lt;br /&gt;
這裡的 book 如 Groovy 第一行來說，已經是List &amp;nbsp;&amp;lt;Book&amp;gt; 了&lt;br /&gt;
book*.getId() 在這裡就是說「 book裡全部的物件都呼叫getId() 並塞到另一個新的List 中」&lt;br /&gt;
於是這個繁瑣的過程就這樣結束了。如果臨時 ui 又需要 book 裡所有的作者&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;["author_list" , book*.getAuthor()] 
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
馬上一行就可以解決並傳到前端去…&lt;br /&gt;
再一次說明，語法上的甜頭，並不是不重要的事，語法上的精簡，可以大大增加&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;易讀性&lt;/li&gt;
&lt;li&gt;開發速度&lt;/li&gt;
&lt;li&gt;減少出錯機率&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-321691874765881314?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/321691874765881314/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/321691874765881314?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/321691874765881314?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/groovy.html' title='Groovy 的一些好用語法(一)  *.'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;AkEFSXw6fCp7ImA9WhJbFEQ.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-7478457965896696974</id><published>2012-09-24T07:56:00.004-07:00</published><updated>2012-09-24T07:56:58.214-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-09-24T07:56:58.214-07:00</app:edited><title>cygwin 在 win7 如何設定ssh</title><content type='html'>浪費了不少時間，請以這一篇做安裝，否則怎樣都會安裝不起來。&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;在安裝cygwin時要選擇什麼。&lt;/li&gt;
&lt;/ul&gt;
這三樣套件記得裝。&lt;br /&gt;
&lt;span style="font-family: 新宋体;"&gt;cygrunsrv&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 新宋体;"&gt;openssh&lt;/span&gt; &lt;br /&gt;
vim&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;環境變數&lt;/li&gt;
&lt;/ul&gt;
&lt;span style="font-family: 新宋体;"&gt;環境變數記得新增一個 CYGWIN=ntsec&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 新宋体;"&gt;在path 這個變數，最後加一個 c:\cygwin\bin &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;如何安裝 ssh&lt;/li&gt;
&lt;/ul&gt;
&lt;span style="background-color: yellow;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: yellow;"&gt;*千萬記住，請按右鍵「以管理者的身份執行」來跑 cygwin 的terminal。否則最後會以沒有足夠的權限失敗做結尾。&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
a.先開權限&lt;br /&gt;
&lt;span sab="503" style="color: red;"&gt;&lt;strong&gt;chmod +r /etc/group&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="503" style="color: red;"&gt;&lt;strong&gt;&lt;span sab="518" style="color: red;"&gt;chmod +r /etc/passwd&lt;span sab="519" style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="503" style="color: red;"&gt;&lt;strong&gt;&lt;span sab="518" style="color: red;"&gt;&lt;span sab="519" style="mso-spacerun: yes;"&gt;&lt;span sab="533" style="color: red;"&gt;chmod +rwx /var/&lt;span sab="534" style="mso-spacerun: yes;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span sab="504" style="mso-spacerun: yes;"&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
b.開始設定&lt;br /&gt;
&lt;span style="color: red;"&gt;&lt;strong&gt;輸入 ssh-host-config &lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
Should privilege separation be used? (yes/no)&lt;b sab="589"&gt;&lt;span sab="590" style="color: red;"&gt; yes&lt;span sab="591" style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;Do you want to install sshd as a service? (yes/no)&lt;b sab="589"&gt;&lt;span sab="590" style="color: red;"&gt; yes&lt;span sab="591" style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;Enter the value of CYGWIN for the daemon: [ntsec] &lt;/span&gt;&lt;span&gt;&lt;strong&gt;ntsec&lt;span sab="637" style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span&gt;&lt;span sab="637" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;Do you want to use a different name? (yes/no) &lt;/span&gt;&lt;span sab="722" style="color: red;"&gt;&lt;strong&gt;no&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span&gt;&lt;span sab="637" style="mso-spacerun: yes;"&gt;&lt;span sab="722" style="color: red;"&gt;&lt;span style="color: black;"&gt;Create new privileged user account 'cyg_server'? (yes/no) &lt;/span&gt;&lt;span&gt;&lt;strong&gt;no&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span&gt;&lt;span sab="637" style="mso-spacerun: yes;"&gt;&lt;span sab="722" style="color: red;"&gt;&lt;span&gt;&lt;span style="color: black;"&gt;Do you want to proceed anyway? (yes/no) &lt;/span&gt;&lt;b sab="750"&gt;&lt;span sab="751" style="color: red;"&gt;yes&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span&gt;&lt;span sab="637" style="mso-spacerun: yes;"&gt;&lt;span sab="722" style="color: red;"&gt;&lt;span&gt;&lt;b sab="750"&gt;&lt;span sab="751" style="color: red;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span style="color: black;"&gt;&lt;span sab="590" style="color: red;"&gt;&lt;span sab="591" style="mso-spacerun: yes;"&gt;&lt;span&gt;&lt;span sab="637" style="mso-spacerun: yes;"&gt;&lt;span sab="722" style="color: red;"&gt;&lt;span&gt;&lt;span sab="751" style="color: red;"&gt;&lt;span sab="796" style="color: red;"&gt;&lt;strong&gt;cygrunsrv.exe -S sshd&lt;/strong&gt; &lt;span style="color: black;"&gt;來試一下是否啟動成功。&lt;span sab="797" style="mso-spacerun: yes;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-7478457965896696974?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/7478457965896696974/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/09/cygwin-win7-ssh.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/7478457965896696974?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/7478457965896696974?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/09/cygwin-win7-ssh.html' title='cygwin 在 win7 如何設定ssh'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;AkQHSH0ycSp7ImA9WhJXFE4.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-1164902039667023288</id><published>2012-08-08T07:57:00.003-07:00</published><updated>2012-08-08T08:05:39.399-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-08T08:05:39.399-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title>jQuery - 如何加入自動完成 ? How to achieve auto complete function?</title><content type='html'>第一步你要先 download jQuery，並且在jsp 中宣告 :
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="js/jquery-1.3.2.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="js/jquery-ui-1.8.7.custom.min.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
版本號就看你下載的jQuery 來宣告。

&lt;br /&gt;
接下來在你的 js 中，針對某一個 input 欄位，此例為料號，加入 auto complete 的功能 。&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;$("#material_text").&lt;span style="color: red;"&gt;&lt;b&gt;autocomplete&lt;/b&gt;&lt;/span&gt;({
        source : function(request, response) {
           
            $.ajax({
                url : $("#path").val() + 'ajax.action?method=list&amp;amp;act=find_material_text',
                type : "POST",
                dataType : "json",
                cache : false,
                delay : 1500,
                data : {
                    term : request.term
                },
                success : function(data) {
                //    $("#material_desc").unblock();
                    response(
                        $.map(data , function(item) {
                            return {
                                label : item.label,
                                value : item.value,
                                desc : item.desc
                            };
                        })
                    );
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus);
                
                }
            });
        },
        select : function(event, ui) {
            $("#product_desc").attr('value', ui.item.desc);            
        }     
    });
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
以下針對上面的程式做簡單說明。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
自動完成，主要是搭配 ajax 的技術，來動態向後端要值。此例是將回傳結果，回傳成類似下拉式的選單，讓使用者可以從這些選單做選擇，而不用記得全部的輸入值資料。可以在 SQL 中做 LIKE ，或是其它搜索方式，讓使用者不一定要從「頭」開始輸入。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
delay 是輸入後趨動查詢的間隔時間，如果使用者想要馬上打馬上看，那間隔可以短一點，不過對後台的呼叫次數當然也會變多，若機器不是很強的時候可以調慢一點。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt; data : {
          term : request.term
         },&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
這是要送到後台去的，term 可以在後面當成一個 parameter 來抓取。就是使用者目前輸入的值。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;select : function(event, ui) {
            $("#product_desc").attr('value', ui.item.desc);            
        } &lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
這裡是指，當使用者「點選了自動完成給你的結果集」之後所觸發的事件。&lt;br /&gt;
若沒有要特別做什麼，這裡可以不用去實作。&lt;br /&gt;
這裡是將 ui.item.desc 的值設入 某個 html input element 中 。&lt;br /&gt;
ui.item 是固定的，就是後台回傳的一個一個物件。&lt;br /&gt;
desc 是你自己可以在後台加入的屬性。&lt;br /&gt;
desc 我是放料號的說明。等下會解釋。&lt;br /&gt;
&lt;br /&gt;
這樣前端的部份大概就好了。再來後端要提供觸發回傳的結果集有哪些。&lt;br /&gt;
至於這一段方法怎麼去觸發，就是看你web framework 使用的是哪一種，簡單來說就是要觸發到這一段，並且要用 ajax + json 的方式吐回去。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;value = p("term");
sb.append("[");
List&amp;lt;Object[]&amp;gt; list = sap.createSQLQuery("select top 500 MATERIAL,MATERIAL_DESC from  MATERIAL where 1=1  and (material like  :val  or MATERIAL_DESC like :val )")
.setParameter("val", "%" + value + "%").list();
int i = 0;
for (Object[] ob : list) {
    sb.append(String.format("{\"label\":\"%s\",\"value\":\"%s\",\"desc\":\"%s\"}", getString(ob[0]) + " " + getString(ob[1]).replaceAll("\"", ""), getString(ob[0]), getString(ob[1])));
    if (i != list.size() - 1)
        sb.append(",");
    i++;
}
sb.append("]");
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
首先我只撈前500筆，若太多的話前端顯示會當掉。&lt;br /&gt;
可以用關鍵字查詢。&lt;br /&gt;
&amp;nbsp;json 裡則有三個屬性 label , value 與 desc ，desc是我自己加的，要和前端的程式同名才能使用。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;label 放料號的 id + 說明。這個是顯示用的。&lt;/li&gt;
&lt;li&gt;value 則放料號的 id。這個值在點了之後，會真的塞到原來的 input field中。&lt;/li&gt;
&lt;li&gt;desc 則只放料號的說明。我拿這個值來塞到畫面別處，讓使用者可以看到很長的料號說明。
將此三值分開，在前端可以方便使用。&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
組json 字串是當初花比較多時間的部份。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); font-family: 'Andale Mono', 'Lucida Console', Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 653px;"&gt;&lt;code&gt;getString = String.valueOf 而已。  p 是取parameter 我自己簡化過的方式。&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-1164902039667023288?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/1164902039667023288/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/jquery-how-to-achieve-auto-complete.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/1164902039667023288?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/1164902039667023288?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/jquery-how-to-achieve-auto-complete.html' title='jQuery - 如何加入自動完成 ? How to achieve auto complete function?'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;AkQARnsyfip7ImA9WhJXFE4.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-8899413225757223678</id><published>2012-08-08T05:29:00.000-07:00</published><updated>2012-08-08T08:05:47.596-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-08T08:05:47.596-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='jQuery'/><title>jQuery - 如何隱藏 select  下的 option. How to hide the options in select using jQuery.</title><content type='html'>$("#sel option").hide(); &amp;nbsp; &amp;nbsp;?&lt;br /&gt;
&lt;br /&gt;
沒辦法耶…&lt;br /&gt;
&lt;br /&gt;
因為hide 不是跨瀏覽器的，至少 IE 8 無法達到這個效果。&lt;br /&gt;
&lt;br /&gt;
網路上有一些solution，但是要以plugin 的方式進行，我覺得沒有必要。&lt;br /&gt;
&lt;br /&gt;
最簡單的原則就是 「把option 搬走」&lt;br /&gt;
&lt;br /&gt;
先宣告變數來裝。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;var from_text="" ;
var to_text="";
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;$("#from_year").change(function(){
            if($(this).val()==''){                                                 
                from_text = $("#from_Q").html();                
                $("#from_Q option").remove();
            }else{
                $("#from_Q").html(from_text);
            }
        });
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
如果年選成空白的時候，把第幾季(Q1-Q4的select)的選擇搬走。&lt;br /&gt;
如果年選回某一年的時候，再把第幾季的文字加回來即可。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-8899413225757223678?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/8899413225757223678/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/jquery-select-option-how-to-hide.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/8899413225757223678?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/8899413225757223678?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/jquery-select-option-how-to-hide.html' title='jQuery - 如何隱藏 select  下的 option. How to hide the options in select using jQuery.'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;DkABRXc_eyp7ImA9WhJXEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-4691686320733112073</id><published>2012-08-03T07:33:00.002-07:00</published><updated>2012-08-03T07:39:14.943-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-03T07:39:14.943-07:00</app:edited><title>Android 如何使用外部gps 裝置?</title><content type='html'>大部份的android 智慧手機早有
GPS&amp;nbsp;&amp;nbsp;晶片，何必還需要開
GPS&amp;nbsp;&amp;nbsp;外部裝置呢?&lt;br /&gt;
我發現手機在「國外」(購買地外) ，打開
GPS&amp;nbsp;&amp;nbsp;後定位的速度異常的慢。&lt;br /&gt;
查了一下才知道手機都有內建搜尋的國家，若非本國來說會比較慢。&lt;br /&gt;
並不清楚我的 GPS 裝置 ( Wintec ) 是否有類似的問題，不過試試看連外部裝置也是不錯的事。&lt;br /&gt;
&lt;br /&gt;
最近離開購買國 ( 荷蘭 ) 後，在比利時旅行時的定位速度非常慢，所以想說透過之前已經買的 Wintec 來做實驗
&lt;br /&gt;
&lt;br /&gt;
首先去Google Play 下載Bluetooth GPS 。&lt;br /&gt;
安裝好之後，打開你的藍芽，也打開你GPS 的藍芽。&lt;br /&gt;
配對。連接。並且勾選用此軟體模擬你內部的GPS 晶片。&lt;br /&gt;
如此一來，你的Google Map 上就會出現小藍點了。中間不需要打開自己手機的 GPS 功能。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
連外部 GPS 比較省電，還是使用內部的GPS 晶片比較省電? 目前還不得而知。&lt;br /&gt;
&lt;br /&gt;
到時候去英國旅行的時候就可以知道效果如何了。&lt;br /&gt;
記得配溫開水服用「google 離線地圖」。&lt;br /&gt;
離線地圖 加 GPS ，真的是個無敵利器!&lt;br /&gt;
大部份的台灣人在本國使用3g 沒有感覺，但是出國旅行的時候，這樣的組合可以讓你免於迷路之苦。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-4691686320733112073?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/4691686320733112073/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/android-gps.html#comment-form' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/4691686320733112073?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/4691686320733112073?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/android-gps.html' title='Android 如何使用外部gps 裝置?'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>1</thr:total></entry><entry gd:etag='W/&quot;CEcDQXo7fCp7ImA9WhJXEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-4807934534849674825</id><published>2012-08-03T06:54:00.000-07:00</published><updated>2012-08-03T06:54:30.404-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-03T06:54:30.404-07:00</app:edited><title>如何將程式碼漂亮的post 在部落格中</title><content type='html'>最簡單的方法，就是去&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://formatmysourcecode.blogspot.nl/"&gt;http://formatmysourcecode.blogspot.nl/&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
將自己的程式貼上，按 format text ，再將結果貼回來即可。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-4807934534849674825?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/4807934534849674825/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/post.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/4807934534849674825?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/4807934534849674825?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/post.html' title='如何將程式碼漂亮的post 在部落格中'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;C0IAQ34zfSp7ImA9WhJXEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-7675014005386463284</id><published>2012-08-03T06:38:00.002-07:00</published><updated>2012-08-03T06:45:42.085-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-03T06:45:42.085-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='sap'/><category scheme='http://www.blogger.com/atom/ns#' term='jco'/><title>Java - 如何透過jco 與 TimerTask 做自動資料同步</title><content type='html'>&lt;b&gt;前提 :&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;自己的資料庫準備好對應的sap表格，欄位名稱和格式要確定好了。&lt;/li&gt;
&lt;li&gt;在servlet 中也要設定這個程式何時要跑，這個就不多提了。&lt;/li&gt;
&lt;li&gt;這個class 會繼承 TimerTask ，當servlet 設定的時間條件觸發時，便會執行。&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;b&gt;說明 :&amp;nbsp;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;本程式提供了成功、失敗寄信的考量。當失敗時會將java exception寄出。&lt;/li&gt;
&lt;li&gt;若sap 的程式有變，只要在db 的表格中新增sap 多的欄位即可，不用動程式。&lt;/li&gt;
&lt;li&gt;每100筆就會flush 出去，不會快速增加無用的暫存記憶體。&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
public void run() {
        Session s = null;
        JCoDestination jCoDestination = null;
        Transaction tx = null;
        Boolean trans_done = false;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
       
        synchronized (this) { // 一次只能有一個進程在執行
            try {    
                Boolean need_to_run = true;
                s = BaseDAO.getSession();
                tx = s.beginTransaction();
                RptLogger.logger.info("== START ==");
                RptLogger.logger.info(new Date());
                //如果沒有執行過 ，或是執行過失敗的時候會自動跑 : 有
              
                if(need_to_run){
 
                    RptLogger.logger.info("try to connect to  SAP Table ...");                                                
                    jCoDestination = ConnectSAPServer.ConnectDETest();
                    RptLogger.logger.info("connect to  SAP Table OK!");
                    JCoFunction function = jCoDestination.getRepository().getFunction("sap 提供的function name");
                    RptLogger.logger.info("get function OK!");
                    if (function == null)
                        throw new RuntimeException("function not found in SAP.");
    
                    // 傳入的參數
                    // SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
                    Calendar ca = Calendar.getInstance();
                    int this_year =  ca.get(Calendar.YEAR);
                    int this_month = ca.get(Calendar.MONTH)+1;
                    ca.add(Calendar.MONTH, -1);
                    int pre_year  = ca.get(Calendar.YEAR);
                    int pre_month = ca.get(Calendar.MONTH)+1;
                    //這邊是視你sap 程式的參數需要而加。
                    function.getImportParameterList().setValue("SALES_YEAR", this_year);
                    function.getImportParameterList().setValue("SALES_MONTH",this_month);
                    function.getImportParameterList().setValue("SALES_YACO", "COGS");
    
                    function.execute(jCoDestination);
    
                    JCoTable returnTable = function.getTableParameterList().getTable("sap 吐出來的表格名稱");
                    RptLogger.logger.info("get SAP Table OK!");
    
                    
                    List&amp;lt;String&amp;gt; header_cols = s.createSQLQuery("select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '你自己db的表格名稱'").list();
                         
                    String sql = "Insert into 你自己db的表格名稱(  ";
                    int x = 0;
                    for (String string : header_cols) {
                        sql = sql + string;
                        if (x != header_cols.size() - 1) {
                            sql = sql + ",";
                        }
                        x++;
                    }
                    x = 0;
                    sql = sql + ") values (";
                    for (String string : header_cols) {
                        sql = sql + "?";
                        if (x != header_cols.size() - 1) {
                            sql = sql + ",";
                        }
                        x++;
                    }
                    sql = sql +" ) ";
                    Query q = s.createSQLQuery(sql);
                 
                    RptLogger.logger.info("There are " + returnTable.getNumRows() + " rows to be inserted.");
                    if (returnTable.getNumRows() &amp;gt; 0) {
                        
                        returnTable.firstRow();
                        for (int i = 0; i &amp;lt; returnTable.getNumRows(); i++, returnTable.nextRow()) { // 總共幾筆資章要塞
                            x = 0;
                            for (String col : header_cols) {
                                q.setParameter(x, returnTable.getValue(col));
                                x++;
                            }
                            q.executeUpdate();
                            if (i % 100 == 0) {
                                s.flush();
                                s.clear();
                            }
                        }
                        s.flush();
                                                                       
                        tx.commit();
                        trans_done = true;
                        RptLogger.logger.info("== YURSWEBFICS END ==");
                    }
                    if(trans_done){                       
                        sendOKEmail();
                    }
                }
            } catch (Exception ex) {
                if (tx != null)
                    tx.rollback();
                ex.printStackTrace();
                StringWriter sw = new StringWriter();
                ex.printStackTrace(new PrintWriter(sw));
                RptLogger.logger.info(sw.toString());                                  
                sendWrongEmail(sw);                                                
            } finally {
                if (s != null &amp;amp;&amp;amp; s.isOpen()) {
                    s.close();
                }
             
            }
        }
    }
    
    private void sendOKEmail() {
        MessageSender msender = MessageSender.getInstance();
        //寄ok信
        
    }

    private void sendWrongEmail(StringWriter sw) {
        MessageSender msender = MessageSender.getInstance();
        //寄失敗信，把java exception 寄出去，讓it可以第一時間抓到問題點。
    }
    
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-7675014005386463284?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/7675014005386463284/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/java-jco-timertask.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/7675014005386463284?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/7675014005386463284?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/java-jco-timertask.html' title='Java - 如何透過jco 與 TimerTask 做自動資料同步'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;C0IBQnk4fCp7ImA9WhJXEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-2124796049857655491</id><published>2012-08-03T06:28:00.001-07:00</published><updated>2012-08-03T06:45:53.734-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-03T06:45:53.734-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='sap'/><category scheme='http://www.blogger.com/atom/ns#' term='jco'/><title>Java - 如何透過jco 連接SAP 程式</title><content type='html'>這一篇主要是一個共用的類別來連結，下一篇會提供可以動態將SAP 吐出來的表格原封不動的塞入自己Database的表格，當然，你這個自己的表格內容要和SAP 的一樣，可以少，但是不可以多。詳細內容是下一篇會介紹。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;package com.deu.report.util;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.DestinationDataProvider;

public class ConnectSAPServer {
     //SAP服務器IP地址 
   // static  String DEI_SAP_CONN_SERVER =   ; 
    //static  String T11 =  "172.test.test.test" ; 
     
    static  String DE_SAP_CONN =  "DE_SAP_CONN" ; 
    static  String DE_TEST_SAP_CONN =  "DE_TEST_SAP_CONN" ; 
     
    static { 
        Properties connectProperties =  new  Properties(); 
        connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "172.test.test.test");  
        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR,   "00" );         //系統編號 
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT,  "025" );        //SAP集團 
        connectProperties.setProperty(DestinationDataProvider.JCO_USER,    "test" );   //SAP用戶名 
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,  "test" );      //密碼 
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG,    "EN" );         //登錄語言 
        connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY,  "3" );   //最大連接數 
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10" );      //最大連接線程 
     
        createDataFile(DEI_SAP_CONN,  "jcoDestination" , connectProperties); 
        
        connectProperties =  new  Properties(); 
        connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "172.16.test.test");  
        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR,   "00" );         //系統編號 
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT,  "025" );        //SAP集團 
        connectProperties.setProperty(DestinationDataProvider.JCO_USER,    "test" );   //SAP用戶名 
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,  "test" );      //密碼 
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG,    "EN" );         //登錄語言 
        connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY,  "3" );   //最大連接數 
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10" );      //最大連接線程 
     
        createDataFile(DE_TEST_SAP_CONN,  "jcoDestination" , connectProperties); 
        
    } 
     
    static  void  createDataFile(String name, String suffix, Properties properties){ 
        File cfg =  new  File( name+ "." +suffix); 
        if (!cfg.exists()){ 
            try { 
                FileOutputStream fos =  new  FileOutputStream(cfg,  false ); 
                properties.store(fos,  "for DEI only !" ); 
                fos.close(); 
            } catch  (Exception e){ 
                throw  new  RuntimeException( "Unable to create the destination file "  + cfg.getName(), e); 
            } 
        } 
    } 
 
    public  static  JCoDestination ConnectDE(){ 
        JCoDestination destination = null ;    
        try  { 
            destination = JCoDestinationManager.getDestination( DE_SAP_CONN ); 
        }  catch  (JCoException e) { 
            e.printStackTrace();
        } 
         
        return  destination; 
    } 
    public  static  JCoDestination ConnectDETest(){ 
        JCoDestination destination = null ;    
        try  { 
            destination = JCoDestinationManager.getDestination( DE_TEST_SAP_CONN ); 
        }  catch  (JCoException e) { 
            e.printStackTrace();
        } 
         
        return  destination; 
    } 
}

&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-2124796049857655491?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/2124796049857655491/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/java-jco-sap.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/2124796049857655491?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/2124796049857655491?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/java-jco-sap.html' title='Java - 如何透過jco 連接SAP 程式'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry><entry gd:etag='W/&quot;C0IMSX08eCp7ImA9WhJXEE0.&quot;'><id>tag:blogger.com,1999:blog-8750838230025517687.post-393007048218254790</id><published>2012-08-03T06:19:00.001-07:00</published><updated>2012-08-03T06:46:28.370-07:00</updated><app:edited xmlns:app='http://www.w3.org/2007/app'>2012-08-03T06:46:28.370-07:00</app:edited><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='sap'/><category scheme='http://www.blogger.com/atom/ns#' term='jco'/><title>Java - jco3 如何在windows + tomcat 下使用 ( 部署篇)</title><content type='html'>SAP JCO 主要用於 Java 呼叫 Sap 程式時使用。當然sap 的程式要開放remote call 與帳號密碼。&lt;br /&gt;
&lt;br /&gt;
1. 首先要下載 jco &amp;nbsp;的不同版本，windows 主要是分32位元與64位元。&lt;br /&gt;
( 這部份可以向貴公司的sap 管理者請求，因為下載時需要提供sap伺服器的資訊 )&lt;br /&gt;
&lt;br /&gt;
2. 將&amp;nbsp;sapjco3.jar 丟到 tomcat 的共用lib 下面。&lt;br /&gt;
&lt;br /&gt;
3. 將&amp;nbsp;sapjco3.dll 丟到 C:\\Windows\System32 下&lt;br /&gt;
&lt;br /&gt;
4. 要安裝&amp;nbsp;Microsoft Visual C++ 2005 SP1 在 tomcat server 那台機器上! 否則無法使用。&lt;br /&gt;
&lt;br /&gt;
下二篇將紀錄如何透過 jco 呼叫 SAP 的程式。&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8750838230025517687-393007048218254790?l=askatheitman.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://askatheitman.blogspot.com/feeds/393007048218254790/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://askatheitman.blogspot.com/2012/08/java-jco3-windows-tomcat.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/393007048218254790?v=2'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8750838230025517687/posts/default/393007048218254790?v=2'/><link rel='alternate' type='text/html' href='http://askatheitman.blogspot.com/2012/08/java-jco3-windows-tomcat.html' title='Java - jco3 如何在windows + tomcat 下使用 ( 部署篇)'/><author><name>Aska</name><uri>http://www.blogger.com/profile/09967987820394438178</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://lh6.ggpht.com/_5foLmJQS3VQ/TLiwOLVFX2I/AAAAAAAAN6Q/4yU_k8SnrFo/s400/R0018288.JPG'/></author><thr:total>0</thr:total></entry></feed>