3

我目前正在开发一个客户端/服务器应用程序。应用服务器是 Glassfish v3,通过远程 EJB 进行通信。主要问题是序列化对象图时使用大量网络带宽。例如在下一个方法中:

@Stateless
public class MyEJB extends MyRemoteInterface {

   @Override
   public PurchaseOrder savePurchaseOrder( PurchaseOrder po ) { ... }

}

这个方法,当远程调用时,将收到一个 PurchesOrder 实例,它是一个对象图,当通过网络传输时,它会占用大量 KB,返回时也是如此。

我已经管理了这个,现在,改变方法的原型是这样的:

...

   @Override
   public byte[] savePurchaseOrder( byte[] po ) { ... }

...

我在通过网络传输 PurchaseOrder 实例之前和之后手动解压缩和反序列化它。但是我松散了类型安全的方法,它变得丑陋了。

有没有办法使用java自定义序列化来压缩默认序列化过程中的输出流?例如:

    @Entity
    public class PurchaseOrder implements Serializable {

       private void writeObject(ObjectOutputStream oos) throws IOException {
           // default serialization 
           oos.defaultWriteObject();

           // COMPRESS STREAM HERE (zip or gzip)
       }

       private void readObject(ObjectInputStream ois) 
           throws ClassNotFoundException, IOException {

           // DECOMPRES STREAM HERE 

           // default deserialization
           ois.defaultReadObject();
       }

    }

我需要“DE/COMPRESS STREAM HERE”部分的代码,或者另一个好主意。

预先感谢您的建议。

泽维尔。

4

5 回答 5

2

这里有一些关于使用自定义序列化的建议很好,但根据您的对象可能需要做很多工作。您可以使用泛型和包装类来获得“有点”更好的实现。

“简单”的实现可能如下所示:

public class ShrinkWrap<E> implements Serializable
{
  private transient E _value;

  public ShrinkWrap(E value) { _value = value; }

  public E get() { return _value; }

  private void writeObject(ObjectOutputStream oos) throws IOException {
    // default serialization 
    oos.defaultWriteObject();

    // compress _value to a byte[] using new ObjectOutputStream(new GZIPOutputStream(new ByteArrayOutputStream()))
    byte[] compValue = ...;

    oos.writeInt(compValue.length);
    oos.write(compValue);
  }

  @SuppressWarnings("unchecked")
  private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
    // default deserialization
    ois.defaultReadObject();

    byte[] compValue = new byte[ois.readInt()];
    ois.readFully(compValue);

    // decompress _value from byte[] using new ObjectInputStream(new GZIPInputStream(new ByteArrayInputStream()))
    _value = ...;
  }
}
于 2012-08-12T19:31:02.850 回答
1

我建议您需要提供一个能够自动压缩/解压缩流的自定义工厂

尝试阅读http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/socketfactory/index.html

于 2012-08-12T19:01:04.917 回答
0

看看JBoss Serialization,值得一看,也许对你有很大帮助。

于 2012-08-12T19:48:33.100 回答
0

您可以使用 DeflatorOutputStream 和 InflatorInputStream 来压缩流。

如果可以的话,我建议使用更紧凑的序列化格式,例如 JSon、Exernalizable 或您自己的二进制格式。这是因为默认的 Java 序列化相对冗长。例如,一个整数使用超过 80 个字节。

于 2012-08-12T19:18:57.353 回答
0

我认为上帝的想法正在使用ZipOutputStream and ZipInputStream. 您可以选择压缩对象的级别并在一个文件中发送多个对象。

于 2012-08-12T19:24:40.883 回答