2008年12月4日 星期四

[DWR] Direct Web Remoting

最近在中大電算中心接的 CASE 中,因為是一個 web platform 的校務系統,又剛好加上 AJAX 的技術,後來 PM 希望可以將原先的 AJAX 改為使用 DWR framework,所以就 survey 了一下這個 framework。

大學時期,上過 Web 2.0 的課程,當初有聽過 DWR 這樣的 framework,只知道可以讓 Java programmer 很快速的開發 AJAX 上的應用,不過當初授課的教授建議我們不要去使用這樣的東西,原因我就忘記了!不過當初 DWR 的版本還是第一版的,可能有一些安全性的問題吧!不過現在已經演進到 DWR 2.0 版本了!

講了一堆無關緊要的東西~讓我們就趕快切入主題吧!

DWR 全名為 Direct Web Remoting,官方網站:http://directwebremoting.org/,由官網的標題就可以知道 DWR 目標在於讓 Java programmer 可以很容易很輕鬆的開發 AJAX 的應用。

DWR 所能夠做到 AJAX 範圍實在廣大,不過因為我只有簡單的使用,所以就將我 survey 到最基礎的技術分享一下吧!

首先,不用我說應該也知道,就是要先下載 DWR 的 JAR 檔案!從網站上的連結就可以取得最新的 dwr.jar 檔案。由於我所使用的 web framework 是 Struts 1,所以我們就將 dwr.jar 放置於 {web project} \ WEB-INF \ lib 之下。

接下來就是要設定一下專按下的 web.xml 檔案,讓 dwr framework 可以在我們開發的 web project 啟動時被抓到。所以我們在 web.xml 中加入:

<servlet>

  <servlet-name>dwr-invoker</servlet-name>

  <servlet-class>

    org.directwebremoting.servlet.DwrServlet

  </servlet-class>

</servlet>

<servlet-mapping>

  <servlet-name>dwr-invoker</servlet-name>

  <url-pattern>/dwr/*</url-pattern>

</servlet-mapping>

更多的 web.xml 設定檔案請按我。設定完成後,我們還要建立一個 dwr.xml 檔案,並放置於 WEB-INF\ 之下,dwr.xml 是設定我們在 server 端的服務與物件,讓前端可以呼叫後端服務的設定檔。在 DWR 2.0 中引進了 annotation的機制,讓我們可以不用撰寫 dwr.xml,有興趣的人可以自行去 survey 這部份!(跟 Struts2 好像~)

我們在 dwr.xml 中的第一行要先加入:

<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://directwebremoting.org/schema/dwr20.dtd">

這樣就可以讓 eclipse 幫我們檢查與產生輔助工具。

接著我們就可以先來撰寫一個 server 端的程式,我們可以很輕巧的建立一個 server 端,因為在 DWR 之下我們並不需要 extends 或 implemented 任何的 class 或 interfaces。這樣我們在開發程式上並不會受到限制,也就是說,我們可以 reuse 過去的 code 等。

public class DWRServer{

    public String sayHello(String name) {

        return "Hello! "+name;

    }

}

這樣的 server 程式夠簡單吧!我還是遵照市面上書籍的慣用 startup example 來示範!

有了後端的程式後,我們當然就要先設定一下我們的 dwr.xml 檔案,這樣在前端的 javascript 才可以呼叫與使用。所以我們就在 dwr.xml 中寫入:

<dwr>

    <allow>

        <create javascript="myHelloServer" creator="new">

            <param name="class" value="DWRServer"></param>

        </create>

    </allow>

</dwr>

dwr.xml 中的 root node 就是 <dwr>,這沒有為什麼,因為就是 DTD 描述的規定。接下來我們就放置 <allow>,告知 DWR 有哪些 server 服務是可以讓前端存取的,與 <allow> 平行的 tags 還有 <init> 與 <signature>,我在這裡就不多加介紹,因為目前在我們的範例中並不會使用到,不過我想聰明的你應該可以大致上猜到這兩個 tags 的用途,因為這蠻直觀的!

再來,我們就要開始描述我們的後端 server 了,所以我們使用 <create> tag,從名稱上我們可以解釋為建立一個新的 server 端服務給前端使用,然後我們可以要指定一個名稱讓前端存取,這個名稱我們要撰寫在 allow tag 中的 javascript attribute 的值,就如同我所寫的 myHelloServer,這個名稱可以隨機取,不過每個 allow tag 彼此的 javascript attribute 的值不可以重複!然後我們要在 allow tag 中寫入 creator="new" 的 attribute 與 value,這應該就是告知 DWR 這是要建立服務的!

有了服務的名稱後,我們在要 allow tag 中 nested 一個 param tag,用來傳入一些參數給 DWR,必要的就是指定 name="class" 與 value 為我們撰寫 server 程式的名稱(要包含 package,我們在這裡使用 default package,所以沒有寫入),這樣 DWR 才可以知道這服務實際上是要呼叫哪個 class。當然,我們可以傳入的 param tag 還可以有其他的設定值。

後端完成後,那我們就要走到前端囉!

前端的撰寫其實也是很簡單,因為我們可以不用自己處理 AJAX 在不同瀏覽器之間的差異性,DWR 都會幫我們去完成這樣複雜且無趣的工作!

回到正題,撰寫前端的 JSP 頁面時,我們必須先在前面加入兩個 javascript 的 references:

<script src='/MyProject/dwr/interface/myHelloServer.js'></script>

<script src='/MyProject/dwr/engine.js'></script>

首先是第一個,這是要告之前端的頁面說我們剛剛設定的服務要匯入,你一定會感到很神奇,我們根本就沒有撰寫 myHelloServer.js 這檔案阿!不過這就是 DWR 會自動去幫你虛擬的產生~至於第二個就比較簡單,因為這是 DWR 必要的一些資源,所以一定要加入的。

接下來就是前端的重頭戲囉~我們要如何在前端呼叫後端的服務呢?相信我,看完接下來的範例後,你一定會驚嘆不已!這真是太神奇了~

在前端我們撰寫以下的 javascript:

function callSayHello(myName) {

    myHelloServer.sayHello(myName, showResult);

}

function showResult(result) {

    document.getElementById("resultText").value = result;

}

第一個 function 是讓我們呼叫 server 端的,我們在裡面可以直接使用 myHelloServer 來當作一個物件,然後呼叫 sayHello,並將參數傳入!有沒有很像在寫 server 端的 JAVA 程式呢?超直觀的~那你一定會問,我們的 sayHello() method 只需要一個 parameter 阿?第二個參數目的?第二個參數是要讓 DWR 在執行完結果後可以 call back 的 function,這樣當我們的呼叫完成後,前端頁面就會呼叫 showResult function。

第二個 function 就是負責將 server 回傳的結果顯示,此 function 的 argument result 是必要的!這是為了接收 server 端的結果之用。我們將 server 回傳的結果簡單的顯示某個 HTML element 上!

簡單的範例就此結束了!神奇吧~我第一次寫完後也覺得超神奇的!

Server 端的回傳不僅僅可以是一個 primary type 或 String,我們也可以放置物件作為回傳參數!這部份,就待續吧~

2 則留言:

Unknown 提到...

当我再页面动态获取数据以后如何再立即获取到数据

Silver Su 提到...

可以請您將您的問題更具體一點的描述嗎?因為不太懂您的意思!