这里是前人的伟大成果。用了以后不太爽,主要问题在ListRangeReader,既然已经要求服务端按照自己的要求组装数据了,为什么还要在客户端做这许多数据解析重组的工作?于是自己做了一个略显干净的实现。
extjs grid所要求的datastore实际上是这样格式的对象:
js 代码
  1. {  
  2.    success: true or false,  
  3.    records: 当前页中的数据项,  
  4.    totalRecords:所有数据总数  
  5. }  

其中的records的每一项为Ext.data.Record类型,这个类型担负着与grid交互的责任,但是其数据部分是简单的:
js 代码
  1. {  
  2.    id: 数据对象的id;  
  3.    data: 真实的数据对象;  
  4. }  

我们先在服务器端按照以上格式把数据组装好。首先是Record
ExtRecord.java
@DataTransferObject
public class ExtRecord {
    long id;
    T data;


    public ExtRecord(long id, T obj) {
        this.id = id;
        this.data = obj;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
之后是datastore
ExtDataStore.java
@DataTransferObject
public interface ExtDataStore {
    @RemoteProperty
    public boolean isSuccess();
    @RemoteProperty
    public List> getRecords();
    @RemoteProperty
    public int getTotalRecords();
}













如果没有特殊要求,使用缺省实现就行了
DefaultExtDataStore.java
public class DefaultExtDataStore implements ExtDataStore{
    boolean success;
    List> records;
    int totalRecords;


    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public List> getRecords() {
        return records;
    }

    public void setRecords(List> records) {
        this.records = records;
    }

    public int getTotalRecords() {
        return totalRecords;
    }

    public void setTotalRecords(int totalRecords) {
        this.totalRecords = totalRecords;
    }
}
































定义一个dwr service模板
public abstract class ExtDWRService<T, M extends HibernateEntityDao<T>> {
    M manager;

    protected void setManager(M manager) {
        this.manager = manager;
    }

    protected ExtDataStore<T> list(int start, int limit, String sort) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        DefaultExtDataStore<T> result = new DefaultExtDataStore<T>();
        result.setSuccess(true);
        List<T> all = manager.getAll();
        result.setTotalRecords(all.size());
        List<ExtRecord<T>> records = new ArrayList<ExtRecord<T>>();
        for(T item : all.subList(start,
                Math.min(start+limit, all.size()))){
            records.add(new ExtRecord<T>(
                    Long.valueOf(BeanUtils.getProperty(item, "id")), item));
        }
        result.setRecords(records);
        return result;
    }

    protected void update(long id, T newValues) throws IllegalAccessException, InvocationTargetException {
        T oldValues = manager.get(id);
        BeanUtils.setProperty(newValues, "id", id);
        org.springside.core.utils.BeanUtils.copyProperties(oldValues, newValues);
        manager.save(oldValues);
    }

    protected T load(long id){
        return manager.get(id);
    }

    protected void add(T newValues) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        T newObj = (T) newValues.getClass().newInstance();
        org.springside.core.utils.BeanUtils.copyProperties(newObj, newValues);
        manager.save(newObj);
    }

    protected void del(long[] ids){
        for(long id: ids){
            manager.removeById(id);
        }
    }

}

这里顺便给出一个具体service实现的例子供参考
public class AdvPositionService extends ExtDWRService<AdvPosition, AdvPositionManager> {
    public void setAdvPositionManager(AdvPositionManager advPositionManager) {
        this.setManager(advPositionManager);
    }

    @RemoteMethod
    public ExtDataStore<AdvPosition> list(int start, int limit, String sort) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        return super.list(start, limit, sort);   
    }

    @RemoteMethod
    public void add(AdvPosition newValues) throws IllegalAccessException, InvocationTargetException, InstantiationException {
        super.add(newValues);
    }

    @RemoteMethod
    public void update(long id, AdvPosition newValues) throws IllegalAccessException, InvocationTargetException {
        super.update(id, newValues);
    }


    @RemoteMethod
    public void del(long[] ids) {
        super.del(ids);
    }

    @RemoteMethod
    public AdvPosition load(long id) {
        return super.load(id);
    }
}

以上是服务端要做的事情。
客户端实现DWRReader(DWRProxy不变)替代ListRangeReader。
js 代码
  1. Ext.data.DWRReader = function() {  
  2.     Ext.data.DWRReader.superclass.constructor.call(thisnull, []);  
  3. }  
  4.   
  5. Ext.extend(Ext.data.DWRReader, Ext.data.DataReader, {  
  6.     read: function(response) {  
  7.         var recordType = this.recordType;  
  8.         var records = [];  
  9.         for (var i = 0; i < response.records.length; i++) {  
  10.             var record = response.records[i]  
  11.             records[records.length] = new recordType(record.data, record.id);  
  12.         }  
  13.         response.records = records;  
  14.         return response;  
  15.     }  
  16. })  
这样dataStore的初始化就很简单了
js 代码
  1. function init_dataStore() {  
  2.     dataStore = new Ext.data.Store({  
  3.         proxy: new Ext.data.DWRProxy(AdvPositionService.list, true),  
  4.         reader: new Ext.data.DWRReader()  
  5.     });  
  6. }  
  7.   
  8. init_dataStore()  
  9. dataStore.load({params:{start:0, limit:myPageSize}});  

最后给几条友情提示:

1. 增删改的操作与grid没有多大关系,可以参考原文自行实现。需要提醒的是,原文中的代码有比较严重的bug,会导致每次添加和修改操作都新建一个对话框实例
2. 以上的java代码使用了SpringSide和apache commons BeanUtils的部分功能,请自行集成,这些对本方案不是必需的,重要的是领会精神
3. 请为你的model声明Converter,另外,dwr的EnumConverter有bug,需要类似于StringConverter在ConvertOutboundData中做encoding
4. 由于dwr的bug,使用本方案有时会出现Warning multiple matching methods. Using first match.的警告,不影响系统运行
5. 总体来说,dwr的使用能够让extjs的代码干净一些,extjs+dwr+spring是我推荐的组合,前提是你有时间和精力去玩儿javascript的诡异语法
6. javaeye的html编辑器会吞掉java代码中的范型,另外草稿第二次保存会丢失我的数据。
评论
qqggcc 2008-09-10   回复
:D  :)  :( 
引用
sariy 2008-01-29   回复
这样在grid 点击列的排序问题怎么解决呢 ??
kaki 2008-01-18   回复
不知道有没有关于tree的方案?
jasonzhl 2008-01-03   回复
正在学习extjs,楼主能否把代码打包发上来,让我们拜读一下,谢谢!!
applebomb 2007-12-28   回复
返回的结构不够好吧?附带数据校验呢?例如说,在一个添加和列表同一个页面时,添加数据后同时刷新列表。那么有可能做数据校验时,将错误的信息返回,这时候需要显示错误信息。而不是列表数据。那么你的错误信息如何返回?

我觉得可以采用

String jsonDataString; //服务器端组织出的json数据
List errorMsg; //多行的错误信息,采用validator国际化效验返回,如果列表为空表示没错误。

来统一处理

然后将业务Bean用AOP方式加工处理
bbyyzhang 2007-10-15   回复
太好了,刚刚使用dwr做了一些功能,看到了ext,正想着要怎样将两者结合呢,楼主这真是及时雨啊!
dotw 2007-10-10   回复
拜读了一下,最近也在用extjs+dwr+spring,和楼主一样对数据在客户端的重组不省其烦.可能上传你的代码参考一下?
发表评论

您还没有登录,请登录后发表评论

半人马
搜索本博客
最近访客
博客分类
最近加入圈子
存档
最新评论
评论排行榜