java—有没有办法检测传入的序列化对象流是gzipoutputstream压缩的还是简单的objectoutputstream?

hiz5n14c  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(302)

我有一个遗留系统,服务器会在几周内缓慢更新。层次结构如下:

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());

这可能吗?谢谢你抽出时间。
-丹尼斯

7d7tgy0s

7d7tgy0s1#

如果gzipinputstream的构造函数不能处理输入流,则会抛出zipexception。
zipexception-如果发生gzip格式错误或不支持使用的压缩方法

hpcdzsge

hpcdzsge2#

您可以读取流的标题。 GZIPOutputStream 先将gzip头写入流中,然后再执行其他操作,以词法十六进制表示,它如下所示:

0x1f8b 0800 0000 0000 0000

来源
请注意,如果您的遗留服务器不使用java的 GZIPOutputStream ,最后8个字节可能不同。但是,前2个字节总是 0x1f8b . 其余的头值只是关于它来自何处以及gzip格式使用的一些其他标志的信息。

ss2ws0br

ss2ws0br3#

@普西有一半的答案。另一半是使用 mark() 以及 reset() 要重置非gzip流的流,请执行以下操作:

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 这里有两个目的:第一,我知道它支持mark/reset。第二,如果底层流没有被缓冲,那么它将提高io性能(尽管,如果它是套接字流,它会被缓冲)。
1024的标记值是任意值。这个 GZipInputStream 构造函数应该能够通过读取前两个字符来确定底层流是否被gzip压缩。但是,gzip头的长度是10字节,因此它可能会尝试读取更多的内容。它不应该读取超过1024个字节(如果是,则增加标记值)。
edit:因为我从您的编辑中看到您正在使用content-type头,所以您还可以使用它来选择性地解压缩流:新服务器将返回如下内容 x-application/java-gzipped-serialized-object 当旧服务器继续返回时 x-application/serialized-java-object (或者不管是什么)。
以“x-”开头的内容类型不受限制;只要双方同意,你想用什么都行。

相关问题