本文BlazeDS技术连接flex和java端,以Remote Object方式传输数据为例,
一、Java端返回数据压缩并在前台解压:
首先建一个类ROResult.java来包装返回的result,如下:
import java.io.Serializable;
public class ROResult implements Serializable {
private static final long serialVersionUID = -6410217400836125781L;
private Object result;
public ROResult(){
}
public ROResult(Object res){
result = res;
}
}
再建立一个压缩后的二进制存放类CompressedResult.java:
import java.io.Serializable;
public class CompressedResult implements Serializable{
private static final long serialVersionUID = 3697351121688911929L;
byte[] data;
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
public CompressedResult(byte[] data){
setData(data);
}
public CompressedResult(){
}
}
以上两个类也需要在前台也建立对应的VO:
ROResult.as:
[RemoteClass(alias="com.model.ROResult")]
public class ROResult {
public var result:Object;
}
CompressedResult.as:
import flash.utils.ByteArray;
[RemoteClass(alias="com.model.CompressedResult")]
public class CompressedResult
{
public function CompressedResult()
{
}
public var data:ByteArray;
}
后台调用压缩方法:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.Amf3Output;
/**
* Try Compress ROResult<br/>
* Result will auto-decompressed by BaseCommand on client side.
* @param result result to compress
* @return true if compressed
*/
public static boolean tryCompressROResult(ROResult result){
if(result==null)return false;
Object ret=result.getResult();
if(ret==null){//do not compress null
return false;
}
byte[] arr=compressAmf(ret);
if(arr!=null){//compress succeeded!
result.setResult(new CompressedResult(arr));
return true;
}
return false;
}
public static final int DEFAULTCOMPRESSINGTHRESHOLD=1024;
public static byte[] compressAmf(Object obj){
return compressAmf(obj,DEFAULTCOMPRESSINGTHRESHOLD);
}
public static byte[] compressAmf(Object obj,int threshold){
if(obj==null)return null;
try{
ByteArrayOutputStream bout = new ByteArrayOutputStream();
SerializationContext context = new SerializationContext();
Amf3Output amf3Output = new Amf3Output(context);
amf3Output.setOutputStream(bout);
amf3Output.writeObject(obj);
amf3Output.flush();
amf3Output.close();
int bufLen=bout.size();
//binary data less than threshold
if(bufLen<=threshold){
return null;
}
byte[] buf=bout.toByteArray();
java.util.zip.Deflater df=
new java.util.zip.Deflater(java.util.zip.Deflater.BEST_COMPRESSION,true);
df.setInput(buf);
df.finish();
//reuse buffer
bout.reset();
byte[] deflatered=new byte[bufLen];
while(!df.finished()){
int len=df.deflate(deflatered);
if(len>0){
bout.write(deflatered,0,len);
}
}
return bout.toByteArray();
}catch(Exception e){
return null;
}
}
该方法将result压缩成二进制并转化成CompressedResult类,存入ROResult中。
而前台需要在flex command中解压,如下解压方法:
import flash.errors.IOError;
import flash.utils.ByteArray;
/**
* Try Decompress ROResult<br/>
* Use with tryCompressROResult on server side
* @return true if content is decompressed
*/
public static function tryDecompressROResult(result:ROResult):Boolean{
if(result==null)return false;
var ret:Object=result.result;
if(ret==null)return false;
if(ret is CompressedResult){
ret=decompressAmf((ret as CompressedResult).data);
if(ret!=null){
result.result=ret;
return true;
}
}
return false;
}
public static function decompressAmf(data:ByteArray):Object{
if(data==null)return null;
try{
if(data is ByteArray){
var b:ByteArray=data as ByteArray;
var compressedLength:int=b.length;
var infStartTime:Number=new Date().getTime();
b.inflate();
var infEndTime:Number=new Date().getTime();
trace("Compressing rate:"+(Number(compressedLength)/b.length));
trace("Decompress time cost:"+(infEndTime-infStartTime));
var ret:Object = b.readObject();
var readEndTime:Number=new Date().getTime();
trace("ReadObject time cost:"+(readEndTime-infEndTime));
return ret;
}
}catch(ex:IOError){
var errInfo:String="IOError during decompressing: "+ex;
trace(errInfo);
throw new Error(errInfo);
}
return null;
}
二、Flex端压缩数据并传输到后台解压:
前台压缩方法:
import flash.utils.ByteArray;
import mx.utils.Base64Decoder;
import mx.utils.Base64Encoder;
/**
* WARNING:CONTENT COMPRESSED
**/
public static function serializeToString(value:Object):String{
if(value==null){
throw new Error("null isn't a legal serialization candidate");
}
var bytes:ByteArray = new ByteArray();
bytes.writeObject(value);
bytes.position = 0;
//compress content
bytes.deflate();
var be:Base64Encoder = new Base64Encoder();
be.encodeBytes(bytes);
var res:String = be.toString();
be.reset();
return res;
}
该方法将数据压缩成字符串string类型。
后台解压方法:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;
import flex.messaging.io.amf.Amf3Output;
import flex.messaging.util.Base64;
/**
* Read Object from base64 string to object<br/>
* WARNING: COMPRESSED!!
* @param <T>
* @param amf
* @param classType
* @return
* @throws ClassNotFoundException
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static <T> T fromAmf(final String amf, Class<T> classType) throws ClassNotFoundException, IOException {
return (T) fromAmf(amf);
}
public static Object fromAmf(final String amf) throws IOException, ClassNotFoundException {
SerializationContext context = new SerializationContext();
final Base64.Decoder decoder = new Base64.Decoder();
decoder.decode(amf);
byte[] input = decoder.flush();
decoder.reset();
//buffer should be compressed!!
input= uncompress(new ByteArrayInputStream(input));
InputStream bIn = new ByteArrayInputStream(input);
Amf3Input amf3Input = new Amf3Input(context);
amf3Input.setInputStream(bIn);
return amf3Input.readObject();
}
private static byte[] uncompress(InputStream is) throws IOException{
java.util.zip.InflaterInputStream infS=new java.util.zip.InflaterInputStream(
is,
new java.util.zip.Inflater(true)
);
ByteArrayOutputStream tmp=new ByteArrayOutputStream();
byte[] buf=new byte[1024];
for(;;){
int len=-1;
try {
len = infS.read(buf);
} catch(EOFException eofe){
break;
}catch (IOException e) {
throw e;
}
if(len==-1){
break;
}
tmp.write(buf,0,len);
}
return tmp.toByteArray();
}
该解压接口fromAmf(final String amf, Class<T> classType)两个参数,分别是前台压缩的字符串和解压后的类型。调用例子:List requestIdList = (List)fromAmf(idListString,List.class);