⼀、理论分析
在学习Redis中的Jedis这⼀部分的时候,要使⽤到Protostuff(Protobuf的Java客户端)这⼀序列化⼯具。⼀开始看到序列化这些字眼的时候,感觉到⼀头雾⽔。于是,参考了⽹上的很多资料,理解了Java序列化与反序列化(参考https://blog.csdn.net/wangloveall/article/details/7992448/),Protobuf的作⽤以及在Java中的使⽤⽅法。 1.Java序列化与反序列化是什么:
Java序列化是指把Java对象转换为字节序列的过程;⽽Java反序列化是指把字节序列恢复为Java对象的过程。 2.为什么需要Java序列化与反序列化 序列化的两种⾮常重要的应⽤:
使⽤序列化将对象集合保存到磁盘⽂件中,并按照它们被存储的样⼦获取它们。通过⽹络将对象集合传送到另⼀台计算机上。 3.为什么只能⽤序列化和反序列化
在磁盘⽂件中,不能去保存和恢复对象的内存地址是因为对象被重载时,它可能占据的是与原来完全不同的内存地址。在⽹络传输中,不同的处理器之间通信时,对象占据的内存地址也是完全不同。 4.序列化和反序列化的好处
序列化就是每个对象都是⽤⼀个序列号保存的,这就是这种机制被称为序列化的原因。 5.实现Java对象序列化与反序列化的⽅法
JDK库中的序列化API实现⼆进制序列化XMLJSONProtostaff
6.JDK库中序列化与反序列化: (1)对象序列化包括如下步骤:
创建⼀个对象输出流,它可以包装⼀个其他类的⽬标输出流,如⽂件输出流;通过对象输出流的writeObject()⽅法写对象。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(\"empoyee.dat\"));Employee harry = new Employee(\"Harry Hacker\Maneger boss = new Manager(\"Carl Cracker\oos.writeObject(harry);oos.writeObject(boss);
(2)对象反序列化包括如下步骤:
创建⼀个对象输⼊流,它可以包装⼀个其他类型的源输⼊流,如⽂件输⼊流;
通过对象输⼊流的readObject()⽅法以这些对象被写出的顺序读取对象并获得它们。
ObjectInputStream ois = new ObjectInputStream (new FileInputStream(\"empoyee.dat\"));Employee e1 = (Employee)ois.readObject();Maneger e2 = (Manager)ois.readObject();
(3)对于那么需要序列化与反序列化的对象,对应的类必须要实现JDK库的相关API,有以下三种⽅法:
若Club类仅仅实现了Serializable接⼝,则可以按照以下⽅式进⾏序列化和反序列化
ObjectOutputStream采⽤默认的序列化⽅式,对Club对象的⾮transient的实例变量进⾏序列化。 ObjcetInputStream采⽤默认的反序列化⽅式,对对Club对象的⾮transient的实例变量进⾏反序列化。
若Club类仅仅实现了Serializable接⼝,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采⽤以下⽅式进⾏序列化与反序列化。 ObjectOutputStream调⽤Student对象的writeObject(ObjectOutputStream out)的⽅法进⾏序列化。 ObjectInputStream会调⽤Student对象的readObject(ObjectInputStream in)的⽅法进⾏反序列化。
若Club类实现了Externalnalizable接⼝,且Club类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)⽅法,则按照以下⽅式进⾏序列化与反序列化。 ObjectOutputStream调⽤Student对象的writeExternal(ObjectOutput out))的⽅法进⾏序列化。 ObjectInputStream会调⽤Student对象的readExternal(ObjectInput in)的⽅法进⾏反序列化。
⼆、⽰例程序分析 1.测试环境:
虚拟机ubuntu 16.04
Jedis版本:Jedis-2.9.0.jar
redis.conf配置⽂件写⼊ubuntu系统ifconfig读取的ip地址:192.168.131.130主机ping 192.168.131.130可以ping通。
2.主机上运⾏eclipse程序,证明可以连接到redis服务器
package bigjun.iplab.jedisConnectTest;import redis.clients.jedis.Jedis;
public class JedisConnectTest {
public static void main(String[] args) { @SuppressWarnings(\"resource\")
Jedis jedis = new Jedis(\"192.168.131.130\"); jedis.set(\"JedisConnectTest\
String getResult = jedis.get(\"JedisConnectTest\"); System.out.println(getResult); }}
控制台输出pass,同时查看ubuntu系统上redis中成功存⼊redis数据。 3.Jedis将对象序列化为⼆进制的API:
public String set(final String key, String value)public String set(final byte[] key, final byte[] value)public byte[] get(final byte[] key)public String get(final String key)
有了这些API的⽀持,就可以将Java对象序列化为⼆进制,当应⽤需要获取Java对象时,使⽤get(final byte[]key)函数将字节数组取出,然后反序列化为Java对象即可。 和很多NoSQL数据库(例如Memcache、Ehcache)的客户端不同,Jedis本⾝没有提供序列化的⼯具,也就是说开发者需要⾃⼰引⼊序列化的⼯具。 4.在测试主机可以成功连接到虚拟机上的redis服务器并且可以存读数据后,考虑如何存读对象。 建⽴⼀个实现了Serializable接⼝的简单对象类Club:
package bigjun.iplab.jdk;import java.io.Serializable;import java.util.Date;
public class Club implements Serializable { /**
* 其实序列化的作⽤是能转化成Byte流,然后⼜能反序列化成原始的类。能 * 在⽹络进⾏传输,也可以保存在磁盘中,
* 有了SUID之后,那么如果序列化的类已经保存了在本地中,
* 中途你更改了类后,SUID变了,那么反序列化的时候就不会变成原始的类了, * 还会抛异常,主要就是⽤于版本控制。 */
private static final long serialVersionUID = 1L;
private int id;
private String name; private String info;
private Date createDate; private int rank;
public Club() { }
public Club(int id, String name, String info, Date createDate, int rank) { super(); this.id = id;
this.name = name; this.info = info;
this.createDate = createDate; this.rank = rank; }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getInfo() { return info; }
public void setInfo(String info) { this.info = info; }
public Date getCreateDate() { return createDate; }
public void setCreateDate(Date createDate) { this.createDate = createDate; }
public int getRank() { return rank; }
public void setRank(int rank) { this.rank = rank; }
5.使⽤JDK库实现序列化和反序列化:
package bigjun.iplab.jdk;
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;
import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.Date;
import redis.clients.jedis.Jedis;public class JDKSerializetionUtil {
public static void main(String[] args) { Jedis jedis = null; try {
jedis = new Jedis(\"192.168.131.130\"); Club club = new Club(); club.setId(1);
club.setName(\"AC\"); club.setInfo(\"⽶兰\");
club.setCreateDate(new Date()); club.setRank(2);
jedis.set(\"JDK\".getBytes(), serialize(club)); byte[] getByte = jedis.get(\"JDK\".getBytes()); Object getObject = unserizlize(getByte); if (getObject instanceof Club) { System.out.println(getObject);
System.out.println(((Club) getObject).getId()); System.out.println(((Club) getObject).getName()); System.out.println(((Club) getObject).getInfo());
System.out.println(((Club) getObject).getCreateDate()); System.out.println(((Club) getObject).getRank()); }
} catch (Exception e) { e.printStackTrace(); } finally {
if (jedis != null) { jedis.close(); } } }
private static byte[] serialize(Object object) {
ObjectOutputStream objectOutputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null; try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(object);
byte[] getByte = byteArrayOutputStream.toByteArray(); return getByte;
} catch (IOException e) { e.printStackTrace(); }
return null; }
private static Object unserizlize(byte[] binaryByte) { ObjectInputStream objectInputStream = null;
ByteArrayInputStream byteArrayInputStream = null;
byteArrayInputStream = new ByteArrayInputStream(binaryByte); try {
objectInputStream = new ObjectInputStream(byteArrayInputStream); Object obj = objectInputStream.readObject(); return obj;
} catch (Exception e) { e.printStackTrace(); }
return null; }}
输出为:
bigjun.iplab.jdk.Club@300ffa5d1AC⽶兰
Sun Jun 03 20:29:24 GMT+08:00 20182
在虚拟机上运⾏get JDK得到:
192.168.131.130:6379> get JDK
\"\\xac\\xed\\x00\\x05sr\\x00\\x15bigjun.iplab.jdk.Club\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x05I\\x00\\x02idI\\x00\\x04rankL\\x00\\ncreateDatet\\x00\\x10Ljava/util/Date;L\\x00\\x04infot\\x00\\x12Ljava/lang/String;L\\x00\\x04nameq\\x00~\\x00\\x02xp\\x00\\x0
再来看⼀下序列化⽅法:
private static byte[] serialize(Object object) {
ObjectOutputStream objectOutputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null; try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(object);
byte[] getByte = byteArrayOutputStream.toByteArray(); return getByte;
} catch (IOException e) { e.printStackTrace(); }
return null; }
ByteArrayOutputStream: ObjectOutputStream: 再来看⼀下反序列⽅法:
private static Object unserizlize(byte[] binaryByte) { ObjectInputStream objectInputStream = null;
ByteArrayInputStream byteArrayInputStream = null;
byteArrayInputStream = new ByteArrayInputStream(binaryByte); try {
objectInputStream = new ObjectInputStream(byteArrayInputStream); Object obj = objectInputStream.readObject(); return obj;
} catch (Exception e) { e.printStackTrace(); }
return null; }
ByteArrayInputStream: ObjectInputStream:
6.使⽤Xml实现序列化和反序列化
⾸先,必须要在要被序列化的对象的类上注释@XmlRootElement(name = \"Club\"),即:
package bigjun.iplab.xml;
import java.io.Serializable;import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
// Xml⽂件中的根标识,必须要表明这个元素,可以让对象和Xml之间⽅便转换@XmlRootElement(name = \"Club\")
public class Club implements Serializable { ...}
然后是在Jedis中利⽤Xml读写Club对象:
package bigjun.iplab.xml;import java.io.StringReader;import java.io.StringWriter;import java.util.Date;
import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBException;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller;import redis.clients.jedis.Jedis;public class XMLSerializetionUtil { public static void main(String[] args) {
Jedis jedis = null; try {
jedis = new Jedis(\"192.168.131.130\"); Club club = new Club(); club.setId(2);
club.setName(\"RM\"); club.setInfo(\"皇马\");
club.setCreateDate(new Date()); club.setRank(1);
jedis.set(\"XML\ String getString = jedis.get(\"XML\");
Object getObject = unserizlize(Club.class, getString); if (getObject instanceof Club) { System.out.println(getObject);
System.out.println(((Club) getObject).getId()); System.out.println(((Club) getObject).getName()); System.out.println(((Club) getObject).getInfo());
System.out.println(((Club) getObject).getCreateDate()); System.out.println(((Club) getObject).getRank()); }
} catch (Exception e) { e.printStackTrace(); } finally {
if (jedis != null) { jedis.close(); } } }
private static String serialize(Object object) { StringWriter stringWriter = null; try {
stringWriter = new StringWriter();
JAXBContext jContext = JAXBContext.newInstance(object.getClass()); Marshaller marshaller = jContext.createMarshaller(); marshaller.marshal(object, stringWriter); } catch (JAXBException e) { e.printStackTrace(); }
return stringWriter.toString(); }
private static Object unserizlize(Class JAXBContext context = JAXBContext.newInstance(clazz); Unmarshaller unmarshaller = context.createUnmarshaller(); StringReader stringReader = new StringReader(xmlString); xmlObject = unmarshaller.unmarshal(stringReader); } catch (JAXBException e) { e.printStackTrace(); } return xmlObject; }} 输出为: bigjun.iplab.xml.Club@1f17ae122RM皇马 Mon Jun 04 09:42:17 GMT+08:00 20181 在虚拟机上运⾏get XML得到: \" 再来分析⼀下序列化⽅法: private static String serialize(Object object) { StringWriter stringWriter = null; try { stringWriter = new StringWriter(); JAXBContext jContext = JAXBContext.newInstance(object.getClass()); Marshaller marshaller = jContext.createMarshaller(); marshaller.marshal(object, stringWriter); } catch (JAXBException e) { e.printStackTrace(); } return stringWriter.toString(); } 再来分析⼀下反序列化⽅法: private static Object unserizlize(Class JAXBContext context = JAXBContext.newInstance(clazz); Unmarshaller unmarshaller = context.createUnmarshaller(); StringReader stringReader = new StringReader(xmlString); xmlObject = unmarshaller.unmarshal(stringReader); } catch (JAXBException e) { e.printStackTrace(); } return xmlObject; } 7.使⽤JSON实现序列化和反序列化 Java下常⽤的JSON⼯具类库主要有以下⼏种: JSON-libFastJsonJacksonGson 1.以JSON-lib为例: 所需的jar包为: Club类不需要添加任何注释,直接看在Jedis中通过JSON读写Club对象类: package bigjun.iplab.json;import java.util.Date; import net.sf.ezmorph.object.DateMorpher;import net.sf.json.JSONObject;import net.sf.json.util.JSONUtils;import redis.clients.jedis.Jedis;public class JDKSerializetionUtil { public static void main(String[] args) { Jedis jedis = null; try { jedis = new Jedis(\"192.168.131.130\"); Club club = new Club(); club.setId(3); club.setName(\"CLE\"); club.setInfo(\"骑⼠\"); club.setCreateDate(new Date()); club.setRank(2); jedis.set(\"JSON\ String getByte = jedis.get(\"JSON\"); Object getObject = unserizlize(getByte); if (getObject instanceof Club) { System.out.println(getObject); System.out.println(((Club) getObject).getId()); System.out.println(((Club) getObject).getName()); System.out.println(((Club) getObject).getInfo()); System.out.println(((Club) getObject).getCreateDate()); System.out.println(((Club) getObject).getRank()); } } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { jedis.close(); } } } private static String serialize(Object object) { JSONObject jsonObject = JSONObject.fromObject(object); String getString = jsonObject.toString(); return getString; } private static Object unserizlize(String jsonString) { new JSONObject(); JSONObject jObject = JSONObject.fromObject(jsonString); JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] { \"MM/dd/yyyy HH:mm:ss\" })); Object jsonObject = JSONObject.toBean(jObject, Club.class); return jsonObject; }} 输出为: 六⽉ 04, 2018 11:02:31 上午 net.sf.json.JSONObject toBean 信息: Property 'day' of class java.util.Date has no write method. SKIPPED.六⽉ 04, 2018 11:02:31 上午 net.sf.json.JSONObject toBean 信息: Property 'timezoneOffset' of class java.util.Date has no write method. SKIPPED.bigjun.iplab.json.Club@2a0981293CLE骑⼠ Mon Jun 04 11:02:30 GMT+08:00 20182 在Redis服务器所在的虚拟机上执⾏get JSON输出为: 192.168.131.130:6379> get JSON \"{\\\"createDate\\\":{\\\"date\\\":4,\\\"day\\\":1,\\\"hours\\\":11,\\\"minutes\\\":2,\\\"month\\\":5,\\\"seconds\\\":30,\\\"time\\\":1528081350946,\\\"timezoneOffset\\\":-480,\\\"year\\\":118},\\\"id\\\":3,\\\"info\\\":\\\"\\xe9\\xaa\\x91\\xe5\\xa3\\xab\\\ 分析使⽤JSON实现序列化代码:将Java对象转换为JSON对象--将JSON对象转换为String类型的字符串。 private static String serialize(Object object) { JSONObject jsonObject = JSONObject.fromObject(object); String getString = jsonObject.toString(); return getString; } 分析使⽤JSON实现反序列化代码:将String类型的JSON字符串转换为JSON对象----将JSON对象转换为Java对象。 private static Object unserizlize(String jsonString) { new JSONObject(); JSONObject jObject = JSONObject.fromObject(jsonString); // 防⽌转换时间错误 JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[] { \"MM/dd/yyyy HH:mm:ss\" })); Object jsonObject = JSONObject.toBean(jObject, Club.class); return jsonObject; } 2.以FastJson为例: (1)FastJson介绍 Fastjson是⼀个Java语⾔编写的⾼性能功能完善的JSON库。它采⽤⼀种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是⽬前Java语⾔中最快的JSON库。Fastjson接⼝简单易⽤,已经被⼴泛使⽤在缓存序列化、协议交互、Web输出、Android客户端等多种应⽤场景。 (2)FastJson优点: FastJson数度快,⽆论序列化和反序列化,都是⽬前Java中最快的。 功能强⼤(⽀持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)。零依赖(没有依赖其它任何类库) (3)FastJson主要API 1. 将对象序列化成json字符串 String com.alibaba.fastjson.JSON.toJSONString(Object object)2. 将json字符串反序列化成对象 JSONObject com.alibaba.fastjson.JSON.parseObject(String text)4.根据key 得到json中的json数组 JSONArray com.alibaba.fastjson.JSONObject.getJSONArray(String key)5. 根据下标拿到json数组的json对象 JSONObject com.alibaba.fastjson.JSONArray.getJSONObject(int index)6.. 根据key拿到json的字符串值 String com.alibaba.fastjson.JSONObject.getString(String key)7. 根据key拿到json的int值 int com.alibaba.fastjson.JSONObject.getIntValue(String key)8. 根据key拿到json的boolean值 boolean com.alibaba.fastjson.JSONObject.getBooleanValue(String key) (4)使⽤FastJson实现在Jedis中读写Club对象(FastJson提供了很完美的API,这⾥就不⽤再多说了,直接使⽤即可) FastJson版本:fastjson-1.2.47.jar package bigjun.iplab.json;import java.util.Date; import com.alibaba.fastjson.JSON;import redis.clients.jedis.Jedis;public class FastJsonSerializetionUtil { public static void main(String[] args) { Jedis jedis = null; try { jedis = new Jedis(\"192.168.131.130\"); Club club = new Club(); club.setId(4); club.setName(\"GS\"); club.setInfo(\"勇⼠\"); club.setCreateDate(new Date()); club.setRank(1); jedis.set(\"FastJson\ String getByte = jedis.get(\"FastJson\"); Object getObject = unserizlize(getByte); if (getObject instanceof Club) { System.out.println(getObject); System.out.println(((Club) getObject).getId()); System.out.println(((Club) getObject).getName()); System.out.println(((Club) getObject).getInfo()); System.out.println(((Club) getObject).getCreateDate()); System.out.println(((Club) getObject).getRank()); } } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { jedis.close(); } } } private static String serialize(Object object) { String getString = JSON.toJSONString(object); return getString; } private static Object unserizlize(String jsonString) { Object jsonObject = JSON.parseObject(jsonString, Club.class); return jsonObject; }} 输出: bigjun.iplab.json.Club@41975e014GS勇⼠ Mon Jun 04 11:25:04 GMT+08:00 20181 虚拟机上执⾏get FastJson的输出(和使⽤JSON-lib⽅式输出的字符串明显短了很多): 192.168.131.130:6379> get FastJson \"{\\\"createDate\\\":1528082704016,\\\"id\\\":4,\\\"info\\\":\\\"\\xe5\\x8b\\x87\\xe5\\xa3\\xab\\\ 8.JSON与XML优缺点对⽐分析 (1)JSON的优点: 与XML相⽐,JSON更加的简洁,我们可以⼀眼就看出其中的内容,⽅便检查排错JSON更加轻量级,不管是编写,传输,还是解析都更加⾼效JSON在传输过程中采⽤了压缩技术,更加的节省宽带 众多的语⾔⽀持,如javascript,python,C,C++等主流语⾔都⽀持 因为JSON格式能直接为服务器端代码使⽤,⼤⼤简化了服务器端和客户端的代码开发量,且完成任务不变,并且易于维护。 (2)XML的优点: 格式统⼀,符合标准; 容易与其他系统进⾏远程交互,数据共享⽐较⽅便 (3)XML的缺点: XML⽂件庞⼤,⽂件格式复杂,传输占带宽; 服务器端和客户端都需要花费⼤量代码来解析XML,导致服务器端和客户端代码变得异常复杂且不易维护;客户端不同浏览器之间解析XML的⽅式不⼀致,需要重复编写很多代码;服务器端和客户端解析XML花费较多的资源和时间。 9.使⽤Protostuff实现序列化与反序列化 (1)Protobuf介绍 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语⾔数据标准,⽬前已经正在使⽤的有超过 48,162 种报⽂格式定义和超过 12,183 个 .proto ⽂件。他们⽤于 RPC 系统和持续数据存储系统。 Protocol Buffers 是⼀种轻便⾼效的结构化数据存储格式,可以⽤于结构化数据串⾏化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可⽤于通讯协议、数据存储等领域的语⾔⽆关、平台⽆关、可扩展的序列化结构数据格式。⽬前提供了 C++、Java、Python 三种语⾔的 API。 (2)Protobuf优点 平台⽆关,语⾔⽆关,可扩展; 提供了友好的动态库,使⽤简单; 解析速度快,⽐对应的XML快约20-100倍; 序列化数据⾮常简洁、紧凑,与XML相⽐,其序列化之后的数据量约为1/3到1/10; 独⽴于语⾔,独⽴于平台,最最重要的是它的效率相当⾼,⽤protobuf序列化后的⼤⼩是json的10分之⼀,xml格式的20分之⼀,是⼆进制序列化的10分之⼀, (3)Protobuf主要流程 需要⾃⼰写⼀个.proto⽂件⽤来描述序列化的格式,然后⽤Protobuf提供的protoc⼯具将.proto⽂件编译成⼀个Java⽂件,最后将该Java⽂件引⼊到项⽬中就可以了。 (4)Protostuff介绍 google原⽣的protobuffer使⽤起来相当⿇烦,⾸先要写.proto⽂件,然后编译.proto⽂件,⽣成对应的.java⽂件。protostuff基于Google Protobuf,好处就是不⽤⾃⼰写.proto⽂件同时在⼏乎不损耗性能的情况下即可实现对象的序列化与反序列化。 (5)使⽤Protostuff⽰例 Protostuff版本: 使⽤Protostuff实现Jedis中Club对象的读取: 代码结构为: 序列化⼯具类ProtostuffSerializer 提供了序列化和反序列化⽅法: package bigjun.iplab.protostuff; import io.protostuff.LinkedBuffer;import io.protostuff.ProtostuffIOUtil;import io.protostuff.Schema; import io.protostuff.runtime.RuntimeSchema; /** * 序列化和反序列化⼯具 */ public class ProtostuffSerializer { private Schema // 序列化⼯具 public byte[] seriable(final Club club) { final LinkedBuffer linkedBuffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { return serializeInternal(club, schema, linkedBuffer); } catch (final Exception e) { throw new IllegalStateException(e.getMessage(), e); } finally { linkedBuffer.clear(); } } // 实际序列化⼯具 private // 反序列化⼯具 public Club deserialize(final byte[] bytes) { try { Club club = deserializeInternal(bytes, schema.newMessage(), schema); if (club != null) { return club; } } catch (final Exception e) { throw new IllegalStateException(e.getMessage(), e); } return null; } // 实际反序列化⼯具 private 测试类: package bigjun.iplab.protostuff;import java.util.Date; import redis.clients.jedis.Jedis;public class ProtostuffSerializetionUtil { public static void main(String[] args) { Jedis jedis = null; try { // ⽣成Jedis对象 jedis = new Jedis(\"192.168.131.130\"); // ⽣成序列化和反序列化⼯具类对象 ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer(); // 定义实体对象 Club club = new Club(5, \"RNG\皇族\new Date(), 1); // 序列化 byte[] clubBytes = protostuffSerializer.serialize(club); // 将club对象写⼊Redis jedis.set(\"Protostuff\".getBytes(), clubBytes); // 从Redis中读取表⽰club对象的字符数组 byte[] getBytes = jedis.get(\"Protostuff\".getBytes()); // 反序列化 Club getClubObject = protostuffSerializer.deserialize(getBytes); if (getClubObject instanceof Club) { System.out.println(getClubObject); System.out.println(((Club) getClubObject).getId()); System.out.println(((Club) getClubObject).getName()); System.out.println(((Club) getClubObject).getInfo()); System.out.println(((Club) getClubObject).getCreateDate()); System.out.println(((Club) getClubObject).getRank()); } } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { jedis.close(); } } }} 输出: bigjun.iplab.protostuff.Club@ed17bee5RNG皇族 Mon Jun 04 15:55:32 GMT+08:00 20181 虚拟机上执⾏get Protostuff的输出(可以看出,长度在⼏种序列化中最短): 192.168.131.130:6379> get Protostuff \"\\b\\x05\\x12\\x03RNG\\x1a\\x06\\xe7\\x9a\\x87\\xe6\\x97\\x8f!\\xf3G\\xcb\\xc9c\\x01\\x00\\x00(\\x01\" 再来看⼀下序列化⼯具: // 序列化⼯具 public byte[] serialize(final Club club) { final LinkedBuffer linkedBuffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { return serializeInternal(club, schema, linkedBuffer); } catch (final Exception e) { throw new IllegalStateException(e.getMessage(), e); } finally { linkedBuffer.clear(); } } // 实际序列化⼯具 private 再看看⼀下反序列化⼯具: // 反序列化⼯具 public Club deserialize(final byte[] bytes) { try { Club club = deserializeInternal(bytes, schema.newMessage(), schema); if (club != null) { return club; } } catch (final Exception e) { throw new IllegalStateException(e.getMessage(), e); } return null; } // 实际反序列化⼯具 private 代码已上传⾄GitHub:https://github.com/BigJunOba/JedisSerialization 因篇幅问题不能全部显示,请点此查看更多更全内容