星期三, 11月 30, 2005

Ajax, JSON, DWR 三部曲

今天報告了 Ajax, JSON 和 DWR,三種方法的實做。順便寫到 blog 上。

Ajax 是 Asynchronous JavaScript Technology and XML 的縮寫,其實這並不是新技術,原理只是說,原本寫網頁的時候,都要按下 submit 動作到後端去處理。會讓原本的網頁重新載入以更新資料。現在改成利用 JavaScript 的方式來達成,按下某一個 button 之後,JavaScript 自動把 form 送出去,然後把回覆的資料(XML的格式)以 DHTML 的方式更新頁面。如此,使用者在處理的時候,就不會有畫面閃動的問題。簡而言之,就是利用 XMLHttpRequest + DHTML。

相信有用過 Gmail Web Mail 的使用者應該有很多體會。例如送出邀請函的方塊,輸入邀請函的 mail送出後 ,會把結果顯示在下面,不會整個頁面重新載入。可以節省 Server 的 loading(每次只傳送需要的資料量)。

不過 Gmail 雖然是這樣的架構,但內部實作並不是使用 XML(拆組 XML總是比較麻煩),而是透過 JSON。JSON 是 JavaScript Object Notation 的縮寫。是 JavaScript 中的 Object 表示法。

像我們若要產生 JavaScript 的物件,會用以下寫法:
var obj = new Object();
obj.a1='abc';
obj.a2=100;
var array1 = new Array(3);
array1[0] = 'a';
array1[1] = 'b';
obj.a3 = array1;

不過,若用 JSON 表示法,則變成如下:
eval('var obj = {"a2":100,"a1":"abc","a3":["a","b"]}');
經過上面執行之後,obj與上個範例的內容是一模一樣的。

JSON for Java 提供了 Java 的 API (3 個 class),可以產生這些表示法。簡單好用。
透過 JSON,用起來就比 AJAX 中操作 XML 的方式來的簡單許多了。
JSON 並不是為了AJAX而產生,是原本就有的。

其中,必須注意的是,Server端都要正確的設定ContentType與編碼,例如使用req.responseXML取得的資料,要指定ContentType=application/xml,XML裡面宣告編碼,或是使用req.responseText的時候,指定ContentType=text/html;charset=big5。 目前知道在 IE 中若使用req.responseText抓取沒指定編碼的資料,會回報 錯誤而停止。

而最後要介紹的就是 DWR (Direct Web Remoting)了。這是一個 java framework,讓想要達到 AJAX 的效果更加方便,不必知道底層是怎樣運作的,中間層會處理掉所有的細節。
更 妙的是,所有的寫法都可以用 JavaBean 來處理(DWR會透過反射機制將資料組成JavaScript的Object)。若仔細研究裡面的細節,會發現,他並非是用 XML 來當溝通媒介,也沒有使用 JSON 的表示法,而是用剛剛寫的第一種產生 JavaScript Object 的方式。若 DWR 可以使用 JSON 的方式,則溝通的訊息量可以節省一半左右,內部實做的程式也會比較簡單。

今天分別用這三種方式實作購物車程式。
第一種方法最麻煩,資料量也最大,第二種方法寫起來直覺很多,傳輸資料量最少,但要用輔助類別(JSON for Java)。第三種方式的程式最簡短,資料量中等(若底層採用JSON應該可以改良)。

到底 AJAX 實不實用呢?其實這並不是新技術,都是舊有的技術。還是要看需求。
有時候,我們開發的時候,也會想用,有時明明想要撈個小資料,也要把整頁資料送到 Server,回到頁面時,還必須把值都帶出來(當然,若用 Struts,資料帶來帶去的麻煩就減少很多了)。
這時候,也可以用用這些技術。反而讓後端程式好寫許多,前端程式則是一定比一般複雜一點點了。

若不想用一堆有的沒有的 Framework,則可以用 JSON來處理,簡單好用。

參考資料:
http://java.sun.com/developer/technicalArticles/J2EE/AJAX/index.html
http://www.crockford.com/JSON/index.html
http://www-128.ibm.com/developerworks/java/library/j-ajax1/
http://www-128.ibm.com/developerworks/java/library/j-ajax2/
http://www-128.ibm.com/developerworks/java/library/j-ajax3/
http://www.dwr.com/

星期四, 11月 10, 2005

小工具

今天被 java service wrapper (http://wrapper.tanukisoftware.org/doc/english/introduction.html) 煩了一陣子。所以就來說說這個東東。

這是把 java 的程式變成 OS service 的小工具。之前是士官長跟我說的,方便又好用。
事實上,也確實是如此。

在 新公司裡,恰巧也有用此工具。我今天在處理將 jdbc driver 換成 type1,說到這,要罵一下 db2, db2 的 jdbc 只有 type1 才有支援 scrollable resultSet,(其實type3應該也可以,不過就無法成功建立連線), 偏偏公司的分頁元件是以此設計的。所以今天在換的過程中,一直出現找不到 db2jdbc 的 native library.

納悶了,明明看 PATH 環境變數都有設定的啊. java 會把 path 的路徑設到 java.library.path 系統 property 中. 除非在執行 java 時,指定 java.library.path。

後來才找到,被 java service wrapper 包裝的 java 程式,不會去抓 PATH 環境變數,要乖乖的設定在 wrapper 的設定檔內: wrapper.java.library.path.1=../lib
我想,最大的原因是因為 java service wrapper 也需要使用 native library, 所以要強迫指定。不過,這也是合理的,被裝成 service 的程式若被環境影響也不太對。

士官長還有介紹一個工具 NSIS (http://nsis.sourceforge.net/Main_Page)
此工具可以做出安裝檔案,重點是還有 eclipse 外掛...
也是簡單好用。
比起 SharpDevelop 裡面所使用的 wix,好用太多了。不過 wix 是會包裝成 msi ,聽說 msi 可以大量遠端安裝,不過這方面我就不清楚了。

星期三, 11月 09, 2005

Tomcat 中實作 SessionListener

實作 SessionListener, 照理說, 應該要在 session timeout 或 session invalidate 之前呼叫...
以讓程式能在可取得 session 之前, 先把資訊做必要的處理.

但在 Tomcat 4.1 中, 會在 session invalidate 之後呼叫, 包括 session timeout 後會先把 session invalidate 之後再呼叫 Listener.

session 都沒用了, 只知道說 session 已經 timeout, 卻無法知道是誰 timeout..
真是奇怪的作法.
我想, 唯一的用途是只能計算目前 session 有幾個吧. :(

不過 Tomcat 5.0 就沒有這個問題了.

話雖如此, 在 Tomcat 4.1 中, 不透過 SessionListener 來處理. 真是會讓程式變得非常難處理.
其他 Listener 都是處理單一 attribute, 問題在於 attribute 之間有關聯, 就麻煩了..
程式會變得很醜.. :(

星期二, 11月 08, 2005

Single Sign On 的作法

最近公司的系統需要配合銀行端所提供的 SSO (Single Sign On) 機制.
這個機制看文件是 IBM 所提供的方法.
在看過這個方法之後, 順便也把之前所寫過的 SSO 方法想過一遍.
其實 IBM 所提供的方法, 我總是覺得怪怪的.
所以把之前的作法, 整理一下, 發表出來.

A 是主控網站, B 是外部系統, db 兩系統需可共用. 使用者必須開啟 cookie.

A 系統來 control 這些 user 是否登入,B 系統發現一位未登入之使用者,則將 Redirect 到 A 系統來判斷是否有登入,Redirect 過去之後,將回覆網址帶過去,當 A 系統發現該 user 已登入,則再 Redirect 到回覆網址中,並帶給 B 系統一個 key. B 系統有了這個 key, 則可以去 access 資料庫.找出該 user 的真實身份, 然後可以自動登入.

說明為啥要開啟 cookie 呢? 原因在於無法使用 url-rewrite 的方式來記錄該 user。若是只有本身的系統,關閉 cookie 還能用 url-rewrite 來達成。跨系統,不使用 cookie 來使用 session 幾乎就沒有其他方法。話是這樣說,但是大部分系統沒有設 cookie 根本就無法運作,在 struts 中,將這種情況考慮進去了,但是若不透過 struts 的標籤的寫法,沒有 cookie 也是會無法運作 session 資料。session and cookie 部份以後再詳細寫一篇好了。

那時想了許多細節可加強與降低 loading. 不過等以後有空再補.