3

我有一个遗留系统,服务器在几周内会慢慢更新。层次结构是这样的:

1
2
3 4 5

1 is the client pc
2 is a master server
3 4 and 5 are servers across the country.

目前所有这些都以未压缩的格式来回发送 POJO(普通的旧 java 对象)。想想 OjbectOutputStream() 等。

我想压缩通过线路序列化的数据,但这样做的方式是只压缩从查询中接收到的数据。向下发送的数据是微不足道的(查询过滤器数据)。

只有客户端 #1 和主服务器 #2 会立即更新。服务器#3、#4 和#5 可以相互间隔数周或数月进行更新。我需要一种方法让服务器#2 能够检测从#3、#4 或#5 返回的流是否被压缩并相应地处理它(当它们升级时)。

-编辑- 对于服务器#3、#4 和#5,解决方案必须不显眼。这些服务器没有发生异常时重新发送数据的概念。

以下是#2 用于与#3、#4 或#5 通信的代码示例:

    // Set the content type to be application/x-java-serialized-object
    connection.setRequestProperty("Content-Type", "application/x-java-serialized-object");

    setupHeaderAttributes(getHttpHeaders());

    setupSessionCookies(getHttpHeaders());

    // Load/add httpHeaders
    addHeadersToConnection(connection, getHttpHeaders());

    // Write the serialized object as post data
    objectoutputstream = new ObjectOutputStream(connection.getOutputStream());
    objectoutputstream.writeObject(obj);
    objectoutputstream.flush();

    // Get ready to receive the reply.
    inputstream = connection.getInputStream();
    setHttpStatus(connection.getResponseCode());

这可能吗?感谢您的时间。

-丹尼斯

4

3 回答 3

1

您可以阅读流的标题。GZIPOutputStream先将 GZIP 标头写入流中,然后在词法十六进制中,它看起来像:

0x1f8b 0800 0000 0000 0000

来源

请注意,如果您的旧服务器不使用 Java GZIPOutputStream,最后 8 个字节可能会有所不同。但是,前 2 个字节将始终为0x1f8b. 剩余的标头值只是关于它来自哪里以及 GZIP 格式使用的一些其他标志的信息。

于 2013-06-06T14:42:58.760 回答
1

@Puce 有一半的答案。另一半是使用mark()reset()重置流,如果它不是 GZipped 流:

    InputStream in = // stream from server
    in = new BufferedInputStream(in);
    in.mark(1024);

    try {
        in = new GZIPInputStream(in);
    }
    catch (ZipException ex) {
        in.reset();
    }

    // "in" is now ready for use

这里BufferedInputStream有两个目的:首先,我知道它支持标记/重置。其次,如果底层流没有缓冲,它将提高 IO 性能(尽管,如果它是套接字流,它将是)。

标记值 1024 是任意值。构造GZipInputStream函数应该能够通过读取前两个字符来确定底层流是否为 GZipped。但是,GZIP 标头的长度为 10 个字节,因此它可能会尝试读取更多内容。它不应读取超过 1024 个字节(如果是,则增加标记值)。


编辑:由于我从您的编辑中看到您正在使用 Content-Type 标头,因此您还可以使用它来选择解压缩流:新服务器将返回类似于x-application/java-gzipped-serialized-object旧服务器继续返回x-application/serialized-java-object(或其他任何内容)的内容.

以“x-”开头的内容类型不受限制;只要两端同意,您就可以使用任何您想要的东西。

于 2013-06-06T15:14:47.720 回答
0

如果GZIPInputStream的构造函数无法处理输入流,则它们会抛出 ZipException。

ZipException - 如果发生 GZIP 格式错误或使用的压缩方法不受支持

于 2013-06-06T14:45:06.430 回答