我为 Actionscript 客户端移植了 BigDecimal 的 IBM ICU 实现。 Someone else has published their nearly identical version here as a google code project.我们的版本增加了一些方便的比较方法。
您可以扩展 Blaze AMF 端点以添加对 BigDecimal 的序列化支持。请注意,另一个答案中的代码似乎不完整,根据我们的经验,它无法在生产中工作。
AMF3 假设重复的对象、特征和字符串是通过引用发送的。对象引用表在序列化时需要保持同步,否则客户端将在反序列化期间失去这些表的同步并开始抛出类转换错误,或破坏不匹配但转换正常的字段中的数据...
以下是更正后的代码:
public void writeObject(final Object o) throws IOException {
if (o instanceof BigDecimal) {
write(kObjectType);
if(!byReference(o)){ // if not previously sent
String s = ((BigDecimal)o).toString();
TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,true,0);
writeObjectTraits(ti); // will send traits by reference
writeUTF(s);
writeObjectEnd(); // for your AmfTrace to be correctly indented
}
} else {
super.writeObject(o);
}
}
还有另一种发送类型对象的方法,它不需要客户端上的 Externalizable。客户端将改为在对象上设置 textValue 属性:
TraitsInfo ti = new TraitsInfo("java.math.BigDecimal",false,false,1);
ti.addProperty("textValue");
writeObjectTraits(ti);
writeObjectProperty("textValue",s);
在任何一种情况下,你的 Actionscript 类都需要这个标签:
[RemoteClass(alias="java.math.BigDecimal")]
Actionscript 类还需要一个文本属性来匹配您选择发送的将初始化 BigDecimal 值的属性,或者在 Externalizable 对象的情况下,需要以下几个方法:
public function writeExternal(output:IDataOutput):void {
output.writeUTF(this.toString());
}
public function readExternal(input:IDataInput):void {
var s:String = input.readUTF();
setValueFromString(s);
}
此代码仅涉及从服务器到客户端的数据。为了反序列化从客户端到服务器的另一个方向,我们选择扩展 AbstractProxy,并使用包装类在创建实际对象之前临时存储 BigDecimal 的字符串值,因为您无法实例化 BigDecimal 然后分配值,正如 Blaze/LCDS 的设计所期望的那样,所有对象都应如此。
这是绕过默认处理的代理对象:
public class BigNumberProxy extends AbstractProxy {
public BigNumberProxy() {
this(null);
}
public BigNumberProxy(Object defaultInstance) {
super(defaultInstance);
this.setExternalizable(true);
if (defaultInstance != null)
alias = getClassName(defaultInstance);
}
protected String getClassName(Object instance) {
return((BigNumberWrapper)instance).getClassName();
}
public Object createInstance(String className) {
BigNumberWrapper w = new BigNumberWrapper();
w.setClassName(className);
return w;
}
public Object instanceComplete(Object instance) {
String desiredClassName = ((BigNumberWrapper)instance).getClassName();
if(desiredClassName.equals("java.math.BigDecimal"))
return new BigDecimal(((BigNumberWrapper)instance).stringValue);
return null;
}
public String getAlias(Object instance) {
return((BigNumberWrapper)instance).getClassName();
}
}
该语句必须在您的应用程序的某个地方执行,以将代理对象绑定到您要控制的类。我们使用静态方法:
PropertyProxyRegistry.getRegistry().register(
java.math.BigDecimal.class, new BigNumberProxy());
我们的包装类如下所示:
public class BigNumberWrapper implements Externalizable {
String stringValue;
String className;
public void readExternal(ObjectInput arg0) throws IOException, ClassNotFoundException {
stringValue = arg0.readUTF();
}
public void writeExternal(ObjectOutput arg0) throws IOException {
arg0.writeUTF(stringValue);
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}