最近接手了一个项目的维护,客户端和服务器间的通信用的是dwr,在增加功能时,突然发现服务器端收到的参数与期望值不一致。比如:
我提供的方法参数为:{TID="PNW20201407070001", DETAILS=[{DNDNUM=3, DNDID=1, DDID="tddetail20140707154558501"}], wfid=21519, opinion="发货中", CDID="DNW20201407070003"},
收到的却是:{TID="PNW20201407070001", DETAILS="[reference:c0-e6]", wfid="21519", opinion="发货中", CDID="DNW20201407070003"}
存在的问题有:1)子对象没有被解析出来,2)非字符串属性被解析为字符串
跟踪dwr的engine.js,发现参数是被完全解析的,是服务器端解析出了问题。在网上搜索此问题,没有发现解决方法。有网友用json,但这样增加了客户端json的打包和服务器端的json解包,大大降低了dwr的使用意义。
结果一番探索,终于解决了这个问题,在此分享给大家,以感谢无数愿意分享技术的网友。
1.重载DefaultConverterManager:
package com.nantian.common.service;
import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import org.directwebremoting.dwrp.DefaultConverterManager;
import org.directwebremoting.extend.InboundContext;
import org.directwebremoting.extend.InboundVariable;
import org.directwebremoting.extend.MarshallException;
import org.directwebremoting.extend.TypeHintContext;
public class ComplexConverterManager extends DefaultConverterManager {
@Override
public Object convertInbound(Class paramType, InboundVariable iv, InboundContext inctx, TypeHintContext incc) throws MarshallException {
Class type = null;
if(paramType==Object.class)
//解析dwr类型数据
type = getExtraTypeInfo(iv.getType(), iv.getValue());
return super.convertInbound(type!=null ? type : paramType, iv, inctx, incc);
}
/**
* 根据数据解析类型
* @param type 数据类型串
* @param value 数据值
* @return 类型
*/
private Class getExtraTypeInfo(String type, String value){
if(type.equalsIgnoreCase("string"))
return String.class;
if(type.equalsIgnoreCase("boolean"))
return Boolean.class;
if(type.equalsIgnoreCase("number")){
if(value.indexOf('.') > -1 || value.indexOf('e') > -1 || value.indexOf('E') > -1)
return Double.class;
Long lv = new Long(value);
return lv.longValue()==lv.intValue() ? Integer.class : Long.class;
}
if(type.equals("Date"))
return Date.class;
if(type.equals("Array"))
return ArrayList.class;
if(type.equals("Object_Object"))
return HashMap.class;
if(type.equals("default"))
return String.class;
return null;
}
@Override
public Class getExtraTypeInfo(TypeHintContext thc) {
Class type = super.getExtraTypeInfo(thc);
//将不能识别的类型标记为Object型,以免被TypeHintContext置为String型
return type!=null ? type : Object.class;
}
}
2.加载ComplexConverterManager:
在web.xml的servlet:dwr-invoker中,增加初始化参数:
<init-param>
<param-name>
org.directwebremoting.extend.ConverterManager
</param-name>
<param-value>
com.nantian.common.service.ComplexConverterManager
</param-value>
</init-param>
如此,客户端的复杂Object或Array对象就可以顺利传递到服务器端了