我的团队正在使用BlazeDS在基于
Spring的服务器上放置一个概念验证Flex应用程序.
我们做了很多日期计算,因此我们在整个代码和域模型中广泛使用Joda Time.
我们现在正试图弄清楚我们如何继续在我们的DTO中使用Joda Time,这些DTO通过BlazeDS与Flex前端来回发送.
我们的目标是在Flex端使用Actionscript 3数据类型Date,并将该映射用于我们在Java端使用Joda time的DateTime,LocalDate和LocalTime类型.
我们可以解决在使用插入BlazeDS的自定义类型marshaller调用Java时转换Actionscript 3的Date类型的问题,但这似乎只针对Flex-> Java / BlazeDS方向调用,而不是针对Java / BlazeDS->调用.弯曲方向.
我现在正在研究BlazeDS的自定义PropertyProxy实现,但这看起来也不正确.
另一个想法是在我们的Java DTO上实现Externalizable,但这看起来似乎太多了,特别是当我看到BlazeDS的竞争对手GraniteDS时,它显示了在他们的文档中使用简单的类型转换器插入Joda Time支持!
任何想法都赞赏.
解决方法
好的 – 我自己找到了答案.这涉及编写我自己的AMF端点类相关的序列化类.我必须说,7000以上的人一直是黑客攻击BlazeDS的灵感源泉.
这段代码应该真正包含在BlazeDS本身或一些开源扩展项目中 – 它是如此基础.
渠道定义
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="ch.hedgesphere.core.blazeds.endpoint.AMFEndpoint"/> <properties> <serialization> <type-marshaller>ch.hedgesphere.core.blazeds.translator.HedgesphereASTranslator</type-marshaller> </serialization> </properties> </channel-definition>
自定义AMF端点
package ch.hedgesphere.core.blazeds.endpoint; import ch.hedgesphere.core.blazeds.serialization.Serializer; public class AMFEndpoint extends flex.messaging.endpoints.AMFEndpoint { @Override protected String getSerializerClassName() { return Serializer.class.getName(); } }
自定义序列化器
package ch.hedgesphere.core.blazeds.serialization; import java.io.OutputStream; import flex.messaging.io.MessageIOConstants; import flex.messaging.io.SerializationContext; import flex.messaging.io.amf.AmfMessageSerializer; import flex.messaging.io.amf.AmfTrace; public class Serializer extends AmfMessageSerializer { @Override public void initialize(SerializationContext context,OutputStream out,AmfTrace trace) { amfOut = new AMF0Output(context); amfOut.setOutputStream(out); amfOut.setAvmPlus(version >= MessageIOConstants.AMF3); debugTrace = trace; isDebug = trace != null; amfOut.setDebugTrace(debugTrace); } }
自定义AMF 0处理
package ch.hedgesphere.core.blazeds.serialization; import flex.messaging.io.SerializationContext; public class AMF0Output extends flex.messaging.io.amf.Amf0Output { public AMF0Output(SerializationContext context) { super(context); } @Override protected void createAMF3Output() { avmPlusOutput = new AMF3Output(context); avmPlusOutput.setOutputStream(out); avmPlusOutput.setDebugTrace(trace); } }
自定义AMF 3处理
package ch.hedgesphere.core.blazeds.serialization; import java.io.IOException; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalTime; import flex.messaging.io.SerializationContext; public class AMF3Output extends flex.messaging.io.amf.Amf3Output { public AMF3Output(SerializationContext context) { super(context); } @Override public void writeObject(Object value) throws IOException { if(value instanceof DateTime) { value = convertToDate((DateTime)value); } if(value instanceof LocalDate) { value = convertToDate((LocalDate)value); } if(value instanceof LocalTime) { value = convertToDate((LocalTime)value); } super.writeObject(value); } private Object convertToDate(LocalTime time) { return time.toDateTimeToday().toDate(); } private Object convertToDate(LocalDate date) { return date.toDateMidnight().toDate(); } private Object convertToDate(DateTime dateTime) { return dateTime.toDate(); } }
自定义Marshaller for Flex-> Java Calling
package ch.hedgesphere.core.blazeds.translator; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalTime; import flex.messaging.io.amf.translator.ASTranslator; public class HedgesphereASTranslator extends ASTranslator { @SuppressWarnings({"rawtypes"}) @Override public Object convert(Object originalValue,Class type) { if( type.equals(DateTime.class)) { return convertToDateTime(originalValue); } if( type.equals(LocalDate.class)) { return convertToLocalDate(originalValue); } if( type.equals(LocalTime.class)) { return convertToLocalTime(originalValue); } return super.convert(originalValue,type); } private Object convertToLocalTime(Object originalValue) { return originalValue == null ? null : new LocalTime(originalValue); } private Object convertToLocalDate(Object originalValue) { return originalValue == null ? null : new LocalDate(originalValue); } private Object convertToDateTime(Object originalValue) { return originalValue == null ? null : new DateTime(originalValue); } @SuppressWarnings({"rawtypes"}) @Override public Object createInstance(Object source,Class type) { return super.createInstance(source,type); } }