protostuff序列化

    在java中,序列化是经常需要使用的,比如对象在网络中传输,那么就必须要序列化后进行传输。而java自带的序列化使用起来虽然方便,但是它序列化后占的体积大,而且不能跨语言,因此在涉及到序列化的时候必然要找到一款高效的序列化框架。在网上查找了一下,发现protostuff使用方便,而且性能比较高,本篇博客简单记录一下ptotostuff如何实现一个序列化和反序列化。

一、需求

       1、有一个用户类(Person)和一个地址类(Address),一个人有多个地址

       2、person中有部分字段不需要序列化

             |-  使用transient修饰即可不进行序列化

       3、当对地址单独序列化时,需要定制化序列化,即有用户判断在什么情况下才可以序列化。(比如:当某个字段不可为空时才可以进行序列化)

             |-  此种情况可以通过自定义Schema进行实现

       4、如果后期序列化的类中新增了字段或删除了字段如何处理,参考  这篇文章, 此处不做处理。

二、实现

1、引入pom文件

<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>io.protostuff</groupId>
				<artifactId>protostuff-bom</artifactId>
				<version>1.4.4</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.protostuff</groupId>
			<artifactId>protostuff-api</artifactId>
		</dependency>
		<dependency>
			<groupId>io.protostuff</groupId>
			<artifactId>protostuff-core</artifactId>
		</dependency>
		<dependency>
			<groupId>io.protostuff</groupId>
			<artifactId>protostuff-runtime</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.18</version>
		</dependency>
	</dependencies>

 注意主要是引入protostuff-core和protostuff-runtime这2个依赖

2、定义Address类

@Data
@Builder
public class Address {
	private String address;
	private String phone;
}

 3、自定义Address的Schema,用于定制化开发,此处简单实现,当address=null时不可进行序列化

/**
 * 自定义Address的Schema,主要是用于定制化开发
 * @描述
 * @作者 huan
 * @时间 2017年12月11日 - 下午9:57:24
 */
public class AddressSchema implements Schema<Address> {

	@Override
	public String getFieldName(int number) {
		String ret = "";
		switch (number) {
		case 1:
			ret = "address";
			break;
		case 2:
			ret = "phone";
		default:
			break;
		}
		return ret;

	}

	@Override
	public int getFieldNumber(String name) {
		if ("address".equals(name)) {
			return 1;
		} else if ("phone".equals(name)) {
			return 2;
		}
		return 0;

	}

	@Override
	public boolean isInitialized(Address message) {
		if (null != message.getAddress()) {
			return true;
		}
		return false;
	}

	@Override
	public Address newMessage() {
		return Address.builder().build();

	}

	@Override
	public String messageName() {
		return Address.class.getSimpleName();
	}

	@Override
	public String messageFullName() {
		return Address.class.getName();

	}

	@Override
	public Class<? super Address> typeClass() {
		return Address.class;
	}

	@Override
	public void mergeFrom(Input input, Address message) throws IOException {
		while (true) {
			int number = input.readFieldNumber(this);
			switch (number) {
			case 0:
				return;
			case 1:
				message.setAddress(input.readString());
				break;
			case 2:
				message.setPhone(input.readString());
				break;
			default:
				input.handleUnknownField(number, this);
			}
		}
	}

	@Override
	public void writeTo(Output output, Address message) throws IOException {
		if (message.getAddress() == null) {
			throw new UninitializedMessageException(message, this);
		}
		output.writeString(1, message.getAddress(), false);
		if (null != message.getPhone()) {
			output.writeString(2, message.getPhone(), false);
		}
	}

}

 注意此处如果不了解,可以先了解一下protobuff,了解一下.proto文件的写法。

            此处做了一个简单的判断,当address==null时,不可进行序列化

4、Person类的开发

@Data
@Builder
public class Person {
	private String name;
	private Integer age;
	private transient String password;
	private List<Address> address;
}

 注意:  1、Person类包含一个Address的列表

           2、注意password字段前面有一个transient,这个表示不进行序列化

           3、@Tag注解可以用于标记字段的顺序号,但是一个类中如果要用则建议都使用

           4、上方是 官网 给出的一个警告,大致意思是:如果你想在一个非静态的内部类上使用@Tag注解,那么最好将这个非静态的内部类改成静态的内部类。
 5、编写测试代码

6、查看结果



 


 

猜你喜欢

转载自huan1993.iteye.com/blog/2404401