Grid-Json数据加载

什么是Grid-Json数据加载

我们开发前台Grid数据加载通常是Rpc查询返回List<...model>方式,后台的数据的序列化和反序列化都是gwt做了,用着其实很方便,但是在我们实际开发中遇到问题就是List的数据量大时,gwt的序列化和反序列化工作是很慢的,存在很大的提升空间。

思路:

我们想想普通的spingMvc模式,返回一个json字符串到前台,几百条的数据根本不会存在序列化的性能问题,是不是我们的gxt-grid请求后台数据也可以用json呢?

当然用json会存在一个问题,就是json怎么转换成前台用的model实体类(这个对于习惯了使用gxt的model实体对象的人来说是很在乎的一个问题)。

经过探索发现gxt已经帮我们封装API把json自动转换成model就是JsonLoadResultReader类,只是我们没有去挖掘它,下面将以出院患者查询说明(做普通的model查询模式500个患者加载时间用了20s-30s,改造通过json方案测试466条数据时间在3s-7s左右)。

Grid-Json使用方法

1、定义好Rpc方法接口,虽然还是用Rpc模式,但是我们的方法返回类型不用List<...model>,直接返回String类型(一个json字符串数据):

void findLeaveHospitalPatientList (PaiVisitModel paiVisitInfoModel, AsyncCallback<String> callback);

 

2、写好Controller获取数据的实现,由于我们返回一个json字符串数据需要将数据转换为json字符串(我用的JsonLib工具),代码中为什么要把数据设置在一个key值为root的Map中,这里是为了配合前台反序列化的逻辑要求:

private JsonConfig cfg = new JsonConfig();
     
public PaiVisitServiceController() {
     cfg.registerJsonValueProcessor(java.util.Date. class ,
             new JsonValueProcessor() {
                 public Object processObjectValue(String key, Object value,
                         JsonConfig arg2) {
                     if (value instanceof Date) {
                         return DateFormatUtils.format((Date)value, "yyyy-MM-dd HH:mm:ss" );
                     }
                     return value;
                 }
                 public Object processArrayValue(Object value,
                         JsonConfig arg1) {
                     return null ;
                 }
             });
@Override
public String findLeaveHospitalPatientList(PaiVisitModel paiVisitInfoModel) {
     PaiVisitInfoVO query = ConvertUtils.convert(PaiVisitInfoVO. class ,
             paiVisitInfoModel);
     List<PaiVisitInfoVO> infoVOs = m_paiVisitService
             .findLeaveHospitalPatientList(query);
     Map<String, Object> map = new HashMap<String, Object>();
     map.put( "root" , infoVOs);
     String json = JSONObject.fromObject(map,cfg).toString();
     return json;
}

3、定义gxt前台反序列化配置,代码中modelType.setRoot("root");的root参数与Controller里面map设置的root参数对应:

public static final ModelType getModelType(){
         ModelType modelType = new ModelType();
         modelType.setRoot( "root" );
         DataField dataField = null ;
         dataField = new DataField( "patientId" );
         modelType.addField(dataField);
         dataField = new DataField( "currentDeptName" );
         modelType.addField(dataField);
         dataField = new DataField( "currentWardName" );
         modelType.addField(dataField);
         dataField = new DataField( "currentNursingUnit" );
         modelType.addField(dataField);
         dataField = new DataField( "currentNursingUnitName" );
         modelType.addField(dataField);
         dataField = new DataField( "admissionDeptName" );
         modelType.addField(dataField);
         dataField = new DataField( "admissionDeptType" );
         modelType.addField(dataField);
         dataField = new DataField( "admissionDeptTypeName" );
         modelType.addField(dataField);
         dataField = new DataField( "introductionEmpId" );
         modelType.addField(dataField);
         dataField = new DataField( "introductionFromHospitalArea" );
         modelType.addField(dataField);
         dataField = new DataField( "introductionToHospitalArea" );
         modelType.addField(dataField);
         dataField = new DataField( "introductionEmpOrgCode" );
         modelType.addField(dataField);
         dataField = new DataField( "paiVisitId" );
         dataField.setType(Long. class );
         modelType.addField(dataField);
         dataField = new DataField( "costType" );
         modelType.addField(dataField);
         dataField = new DataField( "admissionDate" );
         dataField.setType(Date. class );
         dataField.setFormat( "yyyy-MM-dd HH:mm:ss" );
         modelType.addField(dataField);
         dataField = new DataField( "endDate" );
         dataField.setType(Date. class );
         dataField.setFormat( "yyyy-MM-dd HH:mm:ss" );
         modelType.addField(dataField);
         dataField = new DataField( "charges" );
         dataField.setType(Double. class );
         modelType.addField(dataField);
}

 

4、前台定义json反序列化成model的JsonLoadResultReader对象并放入store中(源码中重写newModelInstance方法很重要,返回一个自己要的model实体对象):

RpcProxy<String> proxy = new RpcProxy<String>() { 
   @Override 
   public void load(Object loadConfig, AsyncCallback<String> callback) { 
    // service.getPosts((PagingLoadConfig) loadConfig, callback); 
       m_paiVisitRpcAsync.findLeaveHospitalPatientList(getPaiVisitModelParam(), callback);
  
}; 
JsonLoadResultReader<ArrayList <PaiVisitModel>> reader = new JsonLoadResultReader<ArrayList <PaiVisitModel>>(PaiVisitModel.getModelType()){
     protected ModelData newModelInstance() {
         return new PaiVisitModel();
     };
}; 
final BaseListLoader<ListLoadResult<PaiVisitModel>> loader = new BaseListLoader<ListLoadResult<PaiVisitModel>>(proxy,reader){
     protected void onLoadSuccess(Object loadConfig, com.extjs.gxt.ui.client.data.ListLoadResult<PaiVisitModel> data) {
         super .onLoadSuccess(loadConfig, data);
         unmask(LeaveHospitalPatientGridpanel. this .getParent());
     }
     
     protected void onLoadFailure(Object loadConfig, Throwable t) {
         super .onLoadFailure(loadConfig, t);
         unmask(LeaveHospitalPatientGridpanel. this .getParent());
         MessageBox.alert( "查询出错" , t.getMessage(), null );
         t.printStackTrace();
     };
};
protected final ListStore<PaiVisitModel> m_listStore = new ListStore<PaiVisitModel>(loader);



5、触发rpc请求:loader.load();

关于Gxt的json

先说缺点:

1、通过上面API的使用可以看出json转换成model需要定义ModelType配置对象,配置json每个key到model字段的类型映射,现在我们维护了pojo和model两个实体类不说,又多出一个ModelType来描述json到Model的转换映射关系,麻烦喽(所以我花了几分钟写了一个小工具,自动生成ModelType的代码);

public static void main(String[] args) {
     Method[] mes = PaiVisitModel. class .getMethods();
     List<String> ecu = Arrays.asList( "getClass" , "getPropertyNames" , "getProperties" , "get" , "getBean" );
     System.out.println( "ModelType modelType = new ModelType();" );
     System.out.println( "modelType.setRoot(\"root\");" );
     System.out.println( "DataField dataField = null;" );
     for (Method method : mes) {
         String name = method.getName();
         if (ecu.contains(name)||!name.startsWith( "get" )) {
             continue ;
         }
         name = StringUtils.uncapitalize(name.replaceFirst( "get" , "" ));
         Class<?> returnType = method.getReturnType();
         if (returnType.isAssignableFrom(String. class )) {
             System.out.println( "modelType.addField(\"" +name+ "\");" );
         } else {
             System.out.println( "dataField = new DataField(\"" +name+ "\");" );
             System.out.println( "dataField.setType(" +returnType.getSimpleName()+ ".class);" );
             if (returnType.isAssignableFrom(Date. class )) {
                 System.out.println( "dataField.setFormat(\"yyyy-MM-dd HH:mm:ss\");" );
             }
             System.out.println( "modelType.addField(dataField);" );
         }
     }
     System.out.println( "return  modelType;" );
}

 

2、另外我探索json转换成model的源码里发现:model里面在嵌套一个model,里面的model不会转换出来;

3、后台需要自己把对象序列化成json;

优点:

1、序列化速度提高了,绕开了gwt的序列化(护士站出院患者加载时间从20s-30s变成3s-7s也还是令人惊喜);

2、一番探索使我发现:不熟悉它时,觉得很麻烦,如果明白熟悉了,就会感觉它有着超灵活的API;

3、因为灵活的API,所以给了我们封装和个性化定制的机会 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值