Scripting Introduction
DWR根據dwr.xml生成和Java代碼類似的Javascript代碼。
相對而言Java同步調用,建立與Java代碼比對的Ajax遠端調用接口的最大挑戰來至與實作Ajax的異步調用特性。
DWR通過引入回調函數來解決這個問題,當結果被傳回時,DWR會調用這個函數。
有兩種推薦的方式來使用DWR實作遠端方法調用。可以通過把回調函數放在參數清單裡,也可以把回調函數放到中繼資料對象裡。
當然也可以把回調函數做為第一個參數,但是不建議使用這種方法。因為這種方法在處理自動處理http對象時(檢視"Alternative Method")上會有問題。這個方法主要是為向下相容而存在的。
簡單的回調函數
假設你有一個這樣的Java方法:
public class Remote {
public String getData(int index) { ... }
}
複制
我們可以在Javascript中這樣使用:
<script type="text/javascript"
src="[WEBAPP]/dwr/interface/Remote.js"> </script>
<script type="text/javascript"
src="[WEBAPP]/dwr/engine.js"> </script>
...
function handleGetData(str) {
alert(str);
}
Remote.getData(42, handleGetData);
複制
42是Java方法getData()的一個參數。
此外你也可以使用這種減縮格式:
Remote.getData(42, function(str) { alert(str); });
複制
調用中繼資料對象(Meta-Data)
另外一種文法時使用"調用中繼資料對象"來指定回調函數和其他的選項。上面的例子可以寫成這樣:
Remote.getData(42, {
callback:function(str) { alert(str); }
});
複制
這種方法有很多優點:易于閱讀,更重要的指定額外的調用選項。
逾時和錯誤處理
在回調函數的中繼資料中你可以指定逾時和錯誤的處理方式。例如:
Remote.getData(42, {
callback:function(str) { alert(str); },
timeout:5000,
errorHandler:function(message) { alert("Oops: " + message); }
});
複制
查找回調函數
有些情況下我們很難區分各種回調選項(記住,Javascript是不支援函數重載的)。例如:
Remote.method({ timeout:3 }, { errorHandler:somefunc });
複制
這兩個參數之一是bean的參數,另一個是中繼資料對象,但是我們不能清楚的告訴DWR哪個是哪個。為了可以跨浏覽器,我們假定null == undefined。 是以目前的情況,規則是:
- 如果第一個或最後一個是一個函數,那麼它就是回調函數,沒有中繼資料對象,并且其他參數都是Java的方法參數。
- 另外,如果最後一個參數是一個對象,這個對象中有一個callback成員,并且它是個函數,那麼這個對象就是中繼資料對象,其他的都是Java方法參數。
- 另外,如果第一個參數是 null ,我們就假設沒有回調函數,并且其他的都是Java方法參數。盡管如此,我們會檢查最後一個參數是不是null,如果是就發出警告。
- 最後如果最後一個參數是null,那麼就沒有callback函數。
- 另外,發出錯誤信号是個糟糕的請求格式。
創造一個與Java對象比對的Javascript對象
假設你有這樣的Java方法:
public class Remote {
public void setPerson(Person p) {
this.person = p;
}
}
複制
Person對象的結構是這樣的:
public Person {
private String name;
private int age;
private Date[] appointments;
// getters and setters ...
}
複制
那麼你可以在Javascript中這樣寫:
var p = {
name:"Fred Bloggs",
age:42,
appointments:[ new Date(), new Date("1 Jan 2008") ]
};
Remote.setPerson(p);
複制
在Javascript沒有出現的字段,在Java中就不會被設定。
因為setter都是傳回'void',我們就不需要使用callback函數了。如果你想要一個傳回void的服務端方法的完整版,你也可以加上callback函數。很明顯DWR不會向它傳遞任何參數。