介绍
上一节用java展示了zookeeper的数据结构。zookeeper不光能创建节点,还能在节点上存储数据。本节就讲述如何用java在zookeeper节点上存储并读出数据。
一、首先是jar包:
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
二、序列化及反序列化介绍
要在zookeeper节点上写入数据以及读取数据,需要对数据进行序列化及反序列化。而这一步不需要我们手工进行,但需要我们给zookeeper客户端设置好序列化工具对象,该对象需要实现org.I0Itec.zkclient.serialize.ZkSerializer接口。下面用java包的序列化功能编写一个zookeeper序列化工具.
ZkSerializer.java
package com.lan.LanUtil.temp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.I0Itec.zkclient.exception.ZkMarshallingError;
import org.I0Itec.zkclient.serialize.ZkSerializer;
public class ZkSerialize implements ZkSerializer{
/**
* 1序列化
*/
@Override
public byte[] serialize(Object data) throws ZkMarshallingError {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(data);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(baos!=null) baos.close();
if(oos!=null) oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 1反序列化
*/
@Override
public Object deserialize(byte[] bytes) throws ZkMarshallingError {
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bais.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
三、在节点上存储及读取数据
创建一个ZookeeperData.java类:
package com.lan.LanUtil.temp;
import java.util.List;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.ZkSerializer;
import com.lan.LanUtil.Student;
public class ZookeeperData {
private static String zkServer = "192.168.9.188:2181";//zookeeper地址
public static void main(String[] args) {
ZkClient zkClient = new ZkClient(zkServer);//创建zookeeper的java客户端连接
if(!zkClient.exists("/LAN")) {
zkClient.createPersistent("/LAN");
}
Student stu1 = new Student();
Student stu2 = new Student();
stu1.setName("刘德华");
stu2.setName("周星驰");
zkClient.setZkSerializer(new ZkSerialize());//这里先设置好序列化工具再写入数据
zkClient.createEphemeral("/LAN/liu", stu1);
zkClient.createEphemeral("/LAN/zhou");
zkClient.writeData("/LAN/zhou", stu2);
showZkPathData(zkClient, "/LAN", new ZkSerialize());//展示LAN目录下的所有子目录
zkClient.close();
}
/**
* 遍历展示目录下的所有节点
* @author LAN
* @date 2018年12月3日
* @param zkClient
* @param root
*/
public static void showZkPathData(ZkClient zkClient, String root, ZkSerializer serializer) {
zkClient.setZkSerializer(serializer);
List<String> children = zkClient.getChildren(root);
if(children.isEmpty()){
return;
}
for(String s:children){
String childPath = root.endsWith("/")?(root+s):(root+"/"+s);
Object data = zkClient.readData(childPath, true);
if(data!=null) {
System.err.println(data.getClass());
}
System.err.println(childPath+"("+data+")");
showZkPathData(zkClient, childPath, serializer);
}
}
}
运行结果如下:
在节点上写入数据可以直接在创建节点时写入,也可以节点创建后再用writeData方法写入。但重要的一点是写入数据前先设置好序列化工具。假如不设置,则会采用默认的java序列化工具。要求序列化和反序列化必须对应,否则就有可能数据存进去后无法读取出来。关于序列化和反序列化,可以选择其他的第三方序列化功能,效率可能会比java自带的序列化功能要好,如kryo序列化工具。
结语
zookeeper 4种类型的节点都可以存储数据,本节只是用临时节点作简单的介绍。zookeeper不光能在节点上写入及读取数据,还可以删除、修改、设置数据版本号等功能,这些功能本文不再作详细介绍。
author:蓝何忠
email:lanhezhong@163.com