当前位置:   article > 正文

Java 序列化之Hessian2完全解读

hessian2

欢迎大家关注本博,同时欢迎大家评论交流,可以给个赞哦!!!

  Serializable 劣势

  实现Serializable接口,可以通过Java的序列化机制自动完成JavaBean的序列化和反序列化过程,亦可以通过ObjectOutputStream.writeObject()和ObjectInputStream.readObject自定义部分序列化过程,但是主要序列化过程还是需要ObjectOutputStream.defaultWiteObject()和ObjectInputStream.defaultReadObject默认操作来完成。

  使用Serializable序列化有一些缺点是无法避免的:

  · Serializable序列化的自定义过程范围狭窄,主要功能还是完全由默认序列化完成,在某些业务场景下,无法取得更好的灵活性。

  · Serializable序列化过程是完全递归,且相对较缓慢。

  · 对于需要禁止序列化的变量,需要增加transient关键字修饰,对于属性变量较多的类,操作较复杂。

  · 无法控制字段的序列化和反序列化方式。

  · Serializable序列化过程在创建对象时不会调用构造方法,因此会缺失构造方法内的逻辑。

  整体来说,Serializable序列化方式的维护、运行效率并不是很高。

  Hessian2 概念

  由于Serializable存在很多问题,这些问题在实际应用中直接影响到系统的各项指标,Hessian2在Serializable基础上做了优化,采用和Serializable类似的方式,但可以获得更快的速度和更小的序列化内容。

  · Hessian2提供了完整的序列化规范,可以允许跨语言实现序列化和反序列化。

  · Hessian2序列化时,将类的描述信息写入序列化文件中,此种方式可以保证反序列化时新旧版本对象的兼容性。

  · Hessian2在内容的序列化上做了优化,Hessian2将需要序列化的多个相同的对象只会写入一次,其他用到该对象的只使用对象的引用,而不重新写入对象的描述信息和值信息。

  · Hessian2虽然较Serializable来说,在性能上存在一定优势,但相对于带有schema的序列化工具(如Thrift、protocol Buffers),是无法相提并论的。

  Maven 依赖

<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.62</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

  Hessian2 工具类

  Hessian2依赖Hessian2Output和Hessian2Input来完成JavaBean的序列化和反序列化,下面提供了Hessian2Utils,其实现了序列化和反序列化的功能。

package com.arhorchin.securitit.serialize.hessian.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;

/**
 * @author Securitit.
 * @note Hessian工具类.
 */
public class Hessian2Utils {

    /**
     * JavaBean序列化.
     * @param javaBean Java对象.
     * @throws Exception 异常信息.
     */
    public static <T> byte[] serialize(T javaBean) throws Exception {
        Hessian2Output ho = null;
        ByteArrayOutputStream baos = null;

        try {
            baos = new ByteArrayOutputStream();
            ho = new Hessian2Output(baos);
            ho.writeObject(javaBean);
            ho.flush();
            return baos.toByteArray();
        } catch (Exception ex) {
            System.out.println("[模拟日志记录]HessianUtils.serialize.异常." + ex.getMessage());
            throw new Exception("HessianUtils.serialize.异常.", ex);
        } finally {
            if (null != ho) {
                ho.close();
            }
        }
    }

    /**
     * JavaBean反序列化.
     * @param serializeData 序列化数据.
     * @throws Exception 异常信息.
     */
    public static <T> T deserialize(byte[] serializeData) throws Exception {
        T javaBean = null;
        Hessian2Input hi = null;
        ByteArrayInputStream bais = null;

        try {
            bais = new ByteArrayInputStream(serializeData);
            hi = new Hessian2Input(bais);
            javaBean = (T) hi.readObject();
            return javaBean;
        } catch (Exception ex) {
            System.out.println("[模拟日志记录]HessianUtils.deserialize.异常." + ex.getMessage());
            throw new Exception("HessianUtils.deserialize.异常.", ex);
        } finally {
            if (null != hi) {
                hi.close();
            }
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

  Hessian2 JavaBean

  基于上面工具类,示例相对就比较简单了,首先定义个JavaBean,命名为Car,详细如下:

package com.arhorchin.securitit.serialize.hessian.bean;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

/**
 * @author Securitit.
 * @note Car Pojo.
 */
public class Car implements Externalizable {

	/**
	 * serialVersionUID.
	 */
	private static final long serialVersionUID = 3943382426658456693L;

	/**
	 * 名称.
	 */
	private String name;

	/**
	 * 价格.
	 */
	private Integer price;

	/**
	 * 颜色.
	 */
	private String color;

	/**
	 * 长度.
	 */
	private transient int length;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getPrice() {
		return price;
	}

	public void setPrice(Integer price) {
		this.price = price;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	@Override
	public String toString() {
		return "{name: \"" + name + "\", price: \"" + price + "\", color: \"" + color + "\", length: \"" + length
				+ "\"}";
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeUTF(name);
		out.writeInt(price);
		out.writeUTF(color);
		out.writeInt(length);
	}

	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		System.out.println("[模拟日志记录]readExternal.");
		
		name = in.readUTF();
		price = in.readInt();
		color = in.readUTF();
		length = in.readInt();
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

  Hessian2 工具类测试

package com.arhorchin.securitit.serialize.hessian;

import com.arhorchin.securitit.serialize.hessian.bean.Car;
import com.arhorchin.securitit.serialize.hessian.utils.Hessian2Utils;

/**
 * @author Securitit.
 * @note HessianUtils测试类.
 */
public class Hessian2UtilsTester {

    public static void main(String[] args) throws Exception {
        byte[] hessian2Data = null;
        Car deserializeCar = null;

        Car car = new Car();
        car.setName("布加迪");
        car.setPrice(12000000);
        car.setColor("红色");
        car.setLength(2980);

        hessian2Data = Hessian2Utils.serialize(car);
        System.out.println("Hessian序列化数据:" + hessian2Data);

        deserializeCar = Hessian2Utils.deserialize(hessian2Data);
        System.out.println("Hessian反序列化数据:" + deserializeCar);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

  运行测试类,输出结果如下:

Hessian序列化数据:[B@4d405ef7
Hessian反序列化数据:{name: "布加迪", price: "12000000", color: "红色", length: "0"}
  • 1
  • 2

  Hessian2 与 Serializable 对比

package com.arhorchin.securitit.serialize.hessian;

import com.arhorchin.securitit.serialize.hessian.bean.Car;
import com.arhorchin.securitit.serialize.hessian.utils.Hessian2Utils;
import com.arhorchin.securitit.serialize.serializable.utils.SerializableUtils;

/**
 * @author Securitit.
 * @note Hessian和Serializable对比测试类.
 */
public class Hessian2VsSerializableTester {

    public static void main(String[] args) throws Exception {
        byte[] hessian2Data = null;
        byte[] serializeData = null;

        Car car = new Car();
        car.setName("布加迪");
        car.setPrice(12000000);
        car.setColor("红色");
        car.setLength(2980);

        hessian2Data = Hessian2Utils.serialize(car);
        System.out.println("Hessian序列化数据:" + hessian2Data);
        System.out.println("Hessian序列化数据大小:" + hessian2Data.length);
        
        serializeData = SerializableUtils.serialize(car);
        System.out.println("Serializable序列化数据:" + serializeData);
        System.out.println("Serializable序列化数据大小:" + serializeData.length);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

  运行测试类,输出结果如下:

Hessian序列化数据:[B@4d405ef7
Hessian序列化数据大小:94
Serializable序列化数据:[B@2e817b38
Serializable序列化数据大小:101
  • 1
  • 2
  • 3
  • 4

  总结

  · 通过对比可以看出,Hessian2序列化后的内容比Serializable相对较小,原因在于其描述对象的方式更加紧凑。

  · 文中提供了Hessian2Utils,可以实现依赖于Hessian2的序列化和反序列化操作。

  若文中存在错误和不足,欢迎指正!

本博微信公众号“超哥说码”,欢迎大家订阅,公众号正在完善中,会及时将更优质的博文推送于您!
在这里插入图片描述

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号