註冊 | 登入 | 全文檢索 | 排行榜 |
» JWorld@TW
» Application Server
» GAE
![]() ![]() |
![]() ![]() ![]() ![]() |
己加入精華區 |
by koji at 2010-01-06 09:51 |
本主題所含的標籤 |
作者 | GAE for Java 心得分享 [精華] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 在貼心得之前,想先請問站長能不能開個 Google App Engine for Java 專門討論版或子版? 回歸正題 前幾天開始把一個非 hello world 的 AP 移植到 GAE,就遇到一些不是 google tutorial 能解決的問題,有些自己找到答案,有些參考網上前人的經驗,分享一些給準備要開始用 GAE 來做正事的人,可以少走一點冤枉路。 .安裝 eclipse 3.4 + app engine plug-in 是最方便的選擇,這不用多說了。 .先搞清楚哪些 API 不能用。或者應該正面表列,搞清楚目前哪些能用。 眾所周知,Google 有公布在沙箱中能用的 API,也就是JRE 類別白名單。 [JRE 類別白名單] http://code.google.com/intl/zh-TW/appengine/docs/java/jrewhitelist.html .但對開發專案而言,這還不夠,還要知道哪些常見的 framework 的哪些版本能符沙箱限制,才可以順利使用。挑選開發的 framework 時,才不會走錯路。 [Will it play in App Engine] (似乎有陣子沒更新了,但還是很值得參考) http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine .上文的小細節要特別注意,我很早就看到 stuts_1 能用,而我最常用的富人的臉 richfaces 3.x 還不能用(官方說 4.0 要針對 GAE 修改為可用),所以就決定用 struts 1.2 和 spring 2.0.8 給它下去開發,結果遇到了 File upload 的鐵板(還是一開始可以,後來 eclipse app engine plugin 某天(就是今天,詳見後述)自動更新成功,才發現被擋了,目前剛開始要解決這個問題,還去發文到 app engine group 去問,不知道會不會被 moderator 罵不會先找舊文章?發完等審核的過程中沒事可做(因為我第一個子系統就是要上載檔案,卡在這裡,沒資料也不方便往下開發測測)去找資料才發現,上面那篇文章裡面有一小段話(雖然是在講 Stripes 但對 struts FormFile 也一樣)有提到這點,事先沒仔細看完,還花時間貼文去問,不過,說不定會有人直接回 patch URL,那就沒白費了。 . to JPA or to JDO? It's a problem. 我個人查了一些資料的評估,覺得是用 JDO 比較好,不過這個見仁見智,因為說不定有人的專案要維持 GAE 與 非GAE 同一份 code,而個人或公司政策是以 JPA 為主,所以選 JPA 對它是比較好選擇,這當然得尊重。我只講一下我選 JDO 的原因:我查到 google 目前用的 JDO/JPA 實作 (datanecleus) 的一名前員工的評論,他說 datanecleus JDO, JPA 兩個實作都有,他認為他有資格針對 datanecleus 及兩個 standard 來評論說 JDO 比較成熟(兩者的版本號碼某種程度也反應此點),用途也比較廣泛,JPA 針對 RDBMS,JDO 則包含但不限於 RDBMS,而大家都知道 Google 用 BigTable,本質就不是 RDBMS,若不想要用 datastore 低階API ,看看 google 自己的入門指南(http://code.google.com/intl/zh-TW/appengine/docs/java/gettingstarted/)都用 JDO 做範例,我當然拿香跟著拜,於是就選用 JDO。 2011/1/9 補充:當真正下去用 GAE/J,就會發現在 GAE/J 用 JDO/JPA 就像綁著兩隻腳游泳(如果你不會游泳,可能無法體會這個比喻),因此不少人會試著使用 low level datastore api 或是一些 datastore api 包裝得比較容易使用的框架,如 Slim3, Objectify, Twig 等。 .Eclipse GAE 專案並非 Dynamic Web Application。當 google app engine plugin 幫你建立一個專案,它的目錄看起就和傳統的 web app 不一樣,所以後遺症之一是那些在 WEB-INF/lib 之內的 jar 並不會自動成為 build path 的一環,於是我用加入 build path 的方式,把相關的 jar 加入了 Referenced Libraries (從 package explorer 看到的 pseudo foler 名稱)讓程式能編譯。問題就來了,這樣做之後,Eclipse 每天第一次開機啟動時,似乎會發生 GAE plugin 自動更新失敗,當時我並不清楚此點,只知道 datanecleus 相關的 jar 有些遺失了,導致編譯失敗,我從備份中找出缺少的 jar,把它放進去 lib 再加入 Referenced libraries,又可以編譯了。結果今天(2010/1/1)把自動更新的錯誤訊息仔細看了一下,猜測應該是我把一些 GAE jar 檔放進 Referenced libraries,雖然硬碟上 WEB-INF/lib 中確實有那些檔,但因為 eclipse 中的 lib folder 看不到那些檔,就報刪除失敗,導致更新失敗(其實某種程度它讓我一開始可以一直測試上載檔案,若是更新成功就會出 exception 了,見上文),後來就把 google 提供的 jar 從 Referenced libraries 刪掉,移回 WEB-INF/lib下,就能自動更新,然後也導致 struts (沒有 patch 以前)再也不能使用 FormFile 了。 才工作幾天,心得說多不多,找時間再寫 Spring JdoTemplate 的使用問題,先寫到這裡,抛磚引玉,如果有本站網友也在開發 GAE 的 webapp,也請您一起來討論,集思廣益。 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
worookie
![]() Small Ship 版主 ![]() 發文: 2092 積分: 21 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() Good! ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
alex2918
![]() ![]() ![]() ![]() ![]() ![]() 發文: 28 積分: 0 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 期待你的SHARING ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() .儘量閱讀英文文件,非常重要。 不知道為什麼(可能是英文版較常更新,或是中文版的翻譯碰到不知如何翻譯的就跳過?)英文版的文件會包含一些你在繁體中文版所沒見過的資料 就以底下兩個關於〔查詢與索引〕的中英文件為例,你在繁體中文版中,根本找不到 Only Ancestor Queries in Transactions 這一個段落的翻譯。 http://code.google.com/intl/en/appengine/docs/java/datastore/queriesandindexes.html http://code.google.com/intl/zh-TW/appengine/docs/java/datastore/queriesandindexes.html 同樣的,因為沒見過 ancestor query(or ancestor filter) 在中文版中出現,所以在底下兩個〔交易〕中英文件中 http://code.google.com/intl/en/appengine/docs/java/datastore/transactions.html http://code.google.com/intl/zh-TW/appengine/docs/java/datastore/transactions.html 中文的〔交易中可以完成什麼〕的段落,中文版寫的是 <中文版> 應用程式在交易時無法執行查詢。不過,應用程式在交易時可以使用金鑰擷取資料存放區實體,且所擷取的實體與交易的其他部分絕對一致。您可以在交易前預先準備金鑰,或在交易中使用金鑰名稱或 ID 建立金鑰。 </中文版> 英文版寫的是 <English> An app can perform a query during a transaction, but only if it includes an ancestor filter. An app can also get datastore entities by key during a transaction. You can prepare keys prior to the transaction, or you can build keys inside the transaction with key names or IDs. </English> 光就這一點,你就知道該儘量以英文版文件為主,要不然至少中英文都打開,做為中英對照閱讀也比只讀中文版安全一些。 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() .圖形處理 GAE/J 目前尚未開放支援 java.awt.* (及其子孫) ,這需要大家去踴躍投票,目前僅支援 google 自己的 Image library。 不支援 java.awt.* 會導致許多認真的應用目前完全無法考慮使用 GAE/J。許多知名的 library/framework 都直接/間接使用 java.awt.*,例如: iText, richfaces, JFreeChart 等等,使得產生報表等基本企業需求難以實現。Google 目前已 Acknowledged 這個問題,但尚未 Accepted(不過也不代表一定不會先做)。即使不做報表應用,小到連產生阻擋惡意程式機器人用的 captcha 也很困難(是有其它路可通,但為了這個小東西自己搞也太辛苦了),目前 captcha 建議方案是使用一些免費的 captcha provider 網站。 . https 支援 目前僅支援使用 *.appspot.com 的網域的程式使用 https。若是一定要使用自己的 domain,就無法使用 https。google 自己的建議方案是要進行方全性的網頁時,將網址轉為 *.appspot.com,其它則延用自己的 domain。 . data 在哪裡? 傳統使用 RDBMS 的工程師,非常習慣利用SQL來操弄資料,包括建立初始資料,修改schema,把玩壞的資料改回來,或是程式變動懶得寫資料轉檔直接用SQL調整等等。 在 GAE 這些事相對變得困難一些,馬上會面臨 administrator 帳號要怎麼建立,Entity 變動該怎麼辦的問題?線上版的 GAE 有 data viewer 工具,SDK 版目前僅有 python (這傢伙真的是 GAE 的一級公民,不過幸好 Java 是1.5級)有 local data viewer 功能,Java 版可能快了。底下這個網址有人弄了個簡易的 data viewer,可以做最基本陽春的操弄。 http://code.google.com/p/gae-data-viewer/wiki/QuickStartup 在 GAE 上,這個 code 和 data 一起迭代成長的路,註定走得比傳統路來的辛苦一點,如果這是將來的趨勢(大家認為會是嗎?)趁早習慣總是好的。 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
jini
![]() SoftLeader Taiwan 版主 ![]() 發文: 1266 積分: 23 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() chart 的部份也許可以考慮 google chart http://code.google.com/intl/zh-TW/apis/chart/ PDF 方面可以考慮 PDFJet http://pdfjet.com/os/download.html 另外 on GAE, GWT 鄉對於 richfaces 應該是比較好的選擇 yes, captcha can use http://captchas.net/ or to use Google Account ----------------------------- on GAE 的確有很多限制, 但是往往那些限制卻是最有趣的地方, (被迫學習新的解決方案 ![]() ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() .Like Query GAE 並不支援任意的 like query,僅支援 starts-with ( LIKE 'prefix%') 這類的 query。對一些需要 LIKE '%pattern%' 這樣查詢方式的應用而言,在目前幾乎是絕望的。 python 有 SearchModel 可用,但 Java 目前尚無對應的功能(1.5級公民就是有差)。 討論區有許多替代方案,主要是動用全文檢索,其中之一是使用 Compass (一個架在 Lucene上的open-source project),但仍有許多困難(索引太大時,初始化會超過 request 的時限)與限制(索引無法放在 RAM, HD)對不大的資料尚可,大量資料幾可說是無法使用。更何況不大的資料量何必殺雞用牛刀?以下這篇討論非常值得一讀。 http://groups.google.com/group/google-appengine-java/browse_thread/thread/da5bf3d73b2ea432/e38dfaf9cd4235f8?lnk=gst&q=full+text+search# 不過凡事都有其好的一面,現在不能用 LIKE,將來有可能就直接用 google 吃飯的傢伙。有人質疑 google 最強的就是網頁全文檢索,為什麼 GAE 裡看不到全文檢索的蹤影?google 員工(Max Ross)在上述網址討論串中有提到,雖然全文檢索支援目前不在google 的六個月的 roadmap 中,但已被標示為 started. 見 http://code.google.com/p/googleappengine/issues/detail?id=217 至於現在就開始用 GAE/J 寫應用又要用 LIKE Query 的人該怎麼辦?只好自己評估是先湊和著用 LIKE 'prefix%' 還是使用 Compass,或是使用自己設計的方法。然後昐望 google 趕快把全文檢索弄好。 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 使用 tag file 注意事項 JSP 的 tag file 相當好用,但用在 GAE/J 時需要特別注意。 當在本機用 SDK/eclipse 發展時,tag file 在使用上並無問題,直到第一次要 deploy 到 app engine時,會發現在 JSP pre-compile 階段就陣亡了。(截至 SDK 1.3.1 時,google 尚未 fix 此問題,最新的1.3.2剛出爐沒幾天,還沒試不知道)錯誤訊息如下: Unable to find a javac compiler; com.sun.tools.javac.Main is not on the classpath. Perhaps JAVA_HOME does not point to the JDK 如果你相信錯誤訊息第三行的字面意義,那不如去相信詐騙集團真的會把錢轉進自己的戶頭還比較快樂。 GAE/J forum 中早已有人提出 workaround,大意是把 JDK 內附的 tools.jar 複製到 GAE/J SDK (或 GAE/J Eclipse plugin 的對應目錄)之 lib/shared 目錄下(若用 Eclipse 記得重啟動),詳細網址如下: http://groups.google.com/group/google-appengine-java/browse_thread/thread/225d7a555cbc0100/e6da42a4f41c3b0d?lnk=gst&q=JAVA_HOME# http://groups.google.com/group/google-appengine-java/browse_thread/thread/175e70cc0c93ded9 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 接下來要談的是一個很嚴重的問題,困擾了許多開發者,甚至導致有些人就此離開 GAE。 GAE/J forum 關鍵字:loading request, cold start, spinup, response time 簡單講就是 GAE/J 會在你的 ap idle 的時候把它 shutdown,然後再在有 incoming request 的時候,啟動一個新的 instance 來 serve 這個 request. 這導致這個 request 等很久才有回應,甚至超過 GAE/J request time limit 30秒而出現 exception。 即使你的 ap 經常被存取,仍可能因為 high request per second 或是同一 host heavy load 而導致在另一處啟動新的 instance 來服務新的 request 而發生如同 idle-then-restart 一般的異常狀況. GAE/J FAQ 一整個 Performance Section 都是在講這個,網址如下: http://code.google.com/intl/en/appengine/kb/java.html#What_Is_A_Loading_Request 常見解決方案: . Google 正在開發付費(不被shutdown)的 JVM. 但不知何時問世 2011/1/9 補充:已經問世,3個 instance 套餐 US$9/月,詳見 http://googleappengine.blogspot.com/2010/12/happy-holidays-from-app-engine-team-140.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+GoogleAppEngineBlog+%28Google+App+Engine+Blog%29 . 用 cron 定時存取自己的 ap 使其不 idle,Google 官方建議不要這樣做(大家都這麼搞,當然不利於整體的 resource,最後可能結果是 Google 取消這種用法,大家一起失效),且也沒有全面解決問題。 . 最有效的方法是降低 ap startup time。 為了達成這點,有人做到了不用 Spring,不用 JDO/JPA,不用任何不必要的 slow (startup time) framework/library,達成了約 1.1秒的 startup time. 不過這代價非常大,值不值得,必須依各人的需求來評估。但這確實是目前最有效的方案。 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
hsuanMAX
![]() ![]() ![]() ![]() ![]() ![]() 發文: 75 積分: 0 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 本來打算要用力衝進去玩得說~~結果看到大大這篇,整個就無力了! ![]() ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 為什麼說 GAE/J 是很有潛力的?就以最近熱門的 Android 手機程式開發來說,除非是完全單機版,否則很可能需要一個 Server。對新創者而言,要開發 Android 手機程式,從 SDK 到 IDE 都可以免費,只需要花時間,Server 程式假設用 Java 來寫也可免費開發。但 Server 主機呢? 當你仔細下去估算一台 24hx365d 的 Server 各種方案的成本,你會發現開銷不小。自己在車庫架站的成本是高速頻寬網路(以台灣變態的上傳頻寬,這特別需要 $),較穩定的主機 (想要 24hx365d 不當機,ECC RAM 恐怕是必須的,還要一台備用主機,萬一硬體故障可以立即抽換),電費,夏天的冷氣(以台灣的氣候變遷,可能春秋也快需要了)等等,最慘的情形是還沒開始收錢,尖峰時段的人數/流量就多到要擴充主機/頻寬。 租用VPS的情形,只是把主機/電/管理的成本改成付給專業廠商,不過好處是至少可以先從最小方案租起。沒經驗的租用者,很可能在各家爛廠商當中一再的搬家/重安裝。 租用 Amazon EC2呢?它的優點在於可以在尖峰時段增加 instance,但一樣是打從一開始就要付錢。不過一旦跨入 EC2,傳統的 RDBMS 也很難再使用,必須開始適應 SimpleDB。而且因為和一般主機/VPS的差異,恐怕在開發階段就得開始租用,以便即早在開發階段就實際測試在真實環境執行時的相容性問題。 2011/1/9補充:Amazon 跟隨潮流,新建帳號一年免費,詳見 http://www.javaworld.com.tw/jute/post/view?bid=9&id=287696&sty=3 唯有 GAE/J,一開始是完全免費的。所以在開發階段和初上線低流量時期,都不需要付費,直到你用超過免費的 quota,即使超過 quota,你仍然可以不付費,只要過了quota reset 期(視你超過的是每分鐘 quota 或是每日 quota 項目),第二分鐘/天又是一條好漢。一旦遇到 quota exceed,你可以認真考慮憑估是否開啟計費這個選項。 GAE/J 有另外的好處是其它方案難以望其項背的,就是跨國性的 data center/load balancing。GAE 會根據你最多的使用者所在的區域,自動在對應的 data center 增加 web ap instance 以及 data store(註:目前 beta 版尚未有此功能,但文字約略提到),所以只要你某區域的使用量夠高,速度相當於租用本地高頻寬網站。即使人數較少的區域,Google 擁有的跨國海纜頻寬(上個月才又開通一條咵太平洋的海纜,google 出資擁有該線路20%的頻寬),前往 google 的 traffic 很可能是走它專屬的海纜的。(最後這點是我的猜測) 最後給一個實際案例,供有興趣開發 Android 線上應用(如遊戲)的人參考 http://groups.google.com/group/google-appengine-java/browse_thread/thread/d16e1be77c6f1bc0 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:mylee] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 底下這個部落格的文章是 4/1 貼的,但顯然不是愚人節的內容 http://googlewebtoolkit.blogspot.com/2010/04/look-ma-no-plugin.html 影片裏的內容,瀏覽器的網址對 GAE 稍有概念的人都看得出來是 app engine 的網址 ( http://http://quake2-gwt-port.appspot.com/ )。不過,當我試著去連,結果是直接被導向至該 Open Source 專案首頁(有可能該站只供特定 IP 測試,其它人會被被導向) 表示 Server 是 host 在 GAE 上。而且從內容介紹,它是把 Jake port 到 GWT,所以無疑地應該是用 GAE/J。 這應該算是個多種未來進行式技術 (GAE/J, HTML Canvas, WebGL, WebSocket, Web Storage) 的展示吧。 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:hsuanMAX] |
funy
![]() ![]() ![]() ![]() ![]() ![]() 發文: 78 積分: 0 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() GAE限制太多,可以直接考慮aws,我已經整個對gae的限制無力了… ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:funy] |
tti
![]() ![]() ![]() ![]() ![]() ![]() 發文: 121 積分: 0 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() 小弟最近正在 survey GAE 提早適應雲端是好事 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:tti] |
tti
![]() ![]() ![]() ![]() ![]() ![]() 發文: 121 積分: 0 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() http://code.google.com/intl/en/appengine/docs/java/datastore/queries.html 這一段我真的看不懂 Properties With Multiple Values Can Have Surprising Behaviors The != operator works as "value is other than" test. So, for example, the filter x != 1 matches an entity with value greater than or less than 1. In Java only, you can use a filter like x != 1 AND x != 2, which acts like "a < 1 OR (a > 1 and a < 2) OR a > 2", so [1, 2] matches, but [1, 2, 3] does not. 為什麼 [1. 2] 是符合 而 [1, 2, 3] 不符合 可以請大大解惑嗎 謝謝 另外文件說在多值的屬性下查詢可能會發生驚奇的事情 所以是不是應該盡量避免在多值的屬性上查詢 ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:tti] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() tti wrote: 這段好像是新加的,我印象中當初這一頁沒看到這個例子(當然,當一個人頭腦退化,不記得幾秒鐘前的事也是很正常的,更不用說十幾月前的事)。我懷疑是寫反了。 最好的方法是弄個例子實測,如果測出來是相反的結果,就可以去提報 issue。這個重責大任就交給你了。 ![]() ![]() ![]() |
作者 | Re:GAE for Java 心得分享 [Re:tti] |
mylee
![]() ![]() ![]() ![]() ![]() ![]() 發文: 764 積分: 1 ![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() tti wrote: 不用客氣! 閱讀 GAE/J 文件是還好,因為它官方文件數量不算多(Google 文件一貫特性),不過在你投入大量精力開發實際應用程式之前,要記得先看 http://www.javaworld.com.tw/jute/post/view?bid=9&id=296493&sty=1&tpg=1&age=0 這篇,免得到時 Google 真的橫材入灶時,換你 gun 聲連連。我個人是不受影響,基本上 Google 若實施新的費率方案只是使它失去它原先宣傳的特色,從用多少付多少,改成超過一定門檻(低於這個門檻儘適用於開發或者本來就是低流量的站)就要付月費,但是費用應該還是比租用高品質同計算能力的 VPS 低,然後還是有自動 scale up 的能力。 另外,如果你看了未來可能實施新費率方案還是不改心意,建議你開發App時直接使用 Slim3 http://sites.google.com/site/slim3appengine/ 這個 framework 真的很好用。loading request 啟動時間很容易做到 1.x 秒以下,完全不需要去租用 3 reserved instances (US$9/month)。它的 datastore 寫習慣了,你甚至會覺得寫 GAE/J 程式比寫使用一般 RDBMS 的程式還要輕鬆簡單。我現在甚至會把它的 controller 用在一般非 GAE/J 的 web ap 上(當然目前要自己修改 source,我準備等下去提交 issue 希望官方版就納入這個功能)。 ![]() ![]() |
|
» JWorld@TW » Application Server » GAE |
![]() ![]() ![]() ![]() |
![]() ![]() ![]() |