DataProvider用于從Server端轉(zhuǎn)載數(shù)據(jù)到瀏覽器中,包含異步和同步兩種執(zhí)行模式。
在Pure Client的開發(fā)模式中,我們主要需要關(guān)注的是Dorado.AjaxDataProvider這個(gè)類。該類內(nèi)部通過Dorado的Ajax引擎向服務(wù)端請(qǐng)求數(shù)據(jù),返回的數(shù)據(jù)格式默認(rèn)應(yīng)為JSON形式。 下面的命令定義了一個(gè)DataSet,同時(shí)設(shè)置該DataSet通過AjaxDataProvider來提取數(shù)據(jù),數(shù)據(jù)事實(shí)上被保存在服務(wù)端data/phones.js文件中。
var dataSet = new Dorado.widget.DataSet({
dataProvider: new Dorado.AjaxDataProvider("data/phones.js"),
dataType: "Phone"
});
Dorado.AjaxDataProvider在發(fā)送Ajax請(qǐng)求時(shí)往往還會(huì)在請(qǐng)求中附帶一些其他的信息,這取決與相應(yīng)DataSet和DataType的設(shè)置。 例如我們?yōu)镈ataSet的parameter屬性定義了內(nèi)容,或者我們聲明了DataSet按照分頁(yè)的方式裝載數(shù)據(jù)。那么這些額外的參數(shù)和分頁(yè)的信息都會(huì)附帶在請(qǐng)求中被一同發(fā)送到服務(wù)器端。目前AjaxDataProvider所支持的額外信息包括:
Dorado.AjaxDataProvider默認(rèn)以POST方式發(fā)起請(qǐng)求,同時(shí)將上述的這些額外信息放置在POST請(qǐng)求的content中。這樣,我們?cè)诜?wù)器端必須擁有一些相應(yīng)的支持才能讀到這些JSON信息。以Java為例,下面給出了一個(gè)可以解析并得到這些JSON信息的Servlet的實(shí)例。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
public class ExampleServiceServlet extends HttpServlet {
private static final String JAVASCRIPT_TOKEN = "javascript";
private static final int BUFFER_SIZE = 4096;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ServletInputStream in = request.getInputStream();
try {
String contentType = request.getContentType();
if (contentType.contains(JAVASCRIPT_TOKEN)) { // 判斷contentType以確認(rèn)客戶端是否是以JSON的信息發(fā)送POST信息
StringBuffer buf = new StringBuffer();
byte[] b = new byte[BUFFER_SIZE];
for (int n; (n = in.read(b)) != -1;) {
buf.append(new String(b, 0, n));
}
JSONObject json = JSONObject.fromObject(buf.toString()); // 利用JSONObject工具類解析并得到了客戶端發(fā)送的JSON信息
// 此處就可以利用這些JSON信息編寫自己的業(yè)務(wù)邏輯了
}
}
finally {
in.close();
}
}
}
當(dāng)然,在有些情況下我們可以希望自己來定義這些額外的信息應(yīng)該如何被傳遞到Server。這時(shí)最好的辦法就是派生出一個(gè)新的DataProvider,并且復(fù)寫其中的getLoadOptions方法。 假設(shè)我們希望將parameter中的個(gè)參數(shù)以及pageSize、pageNo全部放到請(qǐng)求的URL參數(shù)中,那么我們可以這樣來定義派生類:
Dorado.MyDataProvider = $extend(Dorado.AjaxDataProvider, {
getLoadOptions: function(arg) {
/* 調(diào)用父類中的處理邏輯
* 由于我們知道原先的邏輯將額外數(shù)據(jù)都放置在jsonData中。因此我們可以從返回的options的jsonData屬性中取得這些信息。
*/
var options = $invokeSuper.call(this, arguments);
var jsonData = options.jsonData;
var parameter = Dorado.Object.apply({}, jsonData.parameter); // 將jsonData中定義的子屬性復(fù)制到parameter中
parameter.pageSize = jsonData.pageSize; // 將pageSize設(shè)置到parameter中
parameter.pageNo = jsonData.pageNo; // 將pageNo設(shè)置到parameter中
options.parameter = parameter;
delete options.jsonData; // 清除原先的jsonData
return options;
}
});
該模式是指和dorado服務(wù)端的代碼整合開發(fā)的場(chǎng)景。在這種場(chǎng)景下,后臺(tái)的Ajax請(qǐng)求是由dorado后端的攔截器攔截并轉(zhuǎn)發(fā)請(qǐng)求的。
在這種模式下我們可以在view設(shè)計(jì)器的model節(jié)點(diǎn)下看到多種類型的DataProvider:
其中最常用的是DirectDataProvider。
例如我們?cè)贘ava后臺(tái)通過annotation技術(shù)定義了一個(gè)DataProvider:
@Component
public class SimpleCRUD {
@Resource
private ProductDao productDao;
@DataProvider
public Collection<Product> getAll() throws Exception {
return productDao.getAll();
}
...
接下來就可以在model中添加一個(gè)DirectDataProvider,并設(shè)置其interceptor屬性:
這樣這個(gè)Provider就知道通過interceptor攔截器去獲取數(shù)據(jù)。
該處使用的是spring:的表達(dá)式,表示要從后臺(tái)的spring服務(wù)中獲取beanId為simpleCRUD的對(duì)象中通過getAll方法獲取數(shù)據(jù)。
設(shè)置好之后我們?cè)僭O(shè)置DataSet的dataProvider為這個(gè)自定義的dataProvider即完成了DataProvider的定義和使用。
當(dāng)然在日常使用中,可以再度簡(jiǎn)化這個(gè)開發(fā)過程,在view中我們可以不用添加DirectDataProvider對(duì)象。而是直接在DataSet的dataProvider對(duì)象上定義:
這種方式會(huì)在dorado的內(nèi)部自動(dòng)創(chuàng)建DirectDataProvider對(duì)象,這種使用方式更為簡(jiǎn)潔一些。
當(dāng)然你在dorado的sample-center中還能看到這種定義方式:
看,這個(gè)地方連spring的id都可以省略。這是基于約定由于配置的一種使用方式,即假設(shè)當(dāng)前View的名稱和對(duì)應(yīng)Spring的id的名稱一樣的情況下,例如本例view的名稱為SimpleCRUD.view.xml,而對(duì)應(yīng)的服務(wù)bean的名稱為"simpleCURD",這種情況下我們就可以直接省略dataProvider屬性配置中beanId的編寫,直接寫#+對(duì)應(yīng)的方法名就可以。
更多建議: