ZkClient之读取数据。

getChildren

在 ZkClient中,可以通过以下API来获取指定节点的子节点列表:

List<String> getChildren(String path)

 ZkClient只提供了一个对外API,用于获取指定节点的子节点列表。这个API的返回值是子节点的相对路径,例如,ZooKeeper服务器上存在/zk-book/c1和/zk-book/c2这样两个节点,那么调用该API获取/zk-book的子节点列表,返回值是[c1, c2]。

和ZooKeeper原生API相比, ZkClient提供 的API没有了Watcher注册的功能。在获取子节点列表这个接口上,可以通过如下API来进行注册监听:

LIst<String> subscribeChanges(String path, IZkChildListener listener)

通过该API的调用,就完成了事件监听的注册。从API方法中,我们可以看出,注册的是对子节点列表的监听,也就是说,一旦子节点列表发生变更,ZooKeeper服务端就会向客户端发出事件通知,由这个Listener来处理。下面给出这个Listener接口的定义:

public interface IZkChildListener {

public void handleChildCHange(String parentPath, List<String> currentChilds) throws Exception;

}

在这个接口定义中,只有一个接口方法handleChildChange,用来处理服务端发送过来的事件通知。该API方法的参数说明如下表所示。

参数名说明
parentPath子节点变更通知对应的父节点的节点路径
currentChilds子节点的相对路径列表,如果没有子节点,那么会传入null

如果客户端对指定节点nodeA注册了IZkChildListener监听,那么将会接收到如下表所示的事件通知。

事件类别说明
新增子节点指定节点nodeA新增子节点。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是最新的子节点列表(相对路径)
减少子节点指定节点nodeA减少子节点。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是最新的子节点列表(相对路径),可能是null
删除节点nodeA指定节点nodeA被删除。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是null

下面,我们通过实际代码来看看getChildren接口以及子节点列表变更监听的使用方式。

// 使用 ZkClient获取子节点列表

public class Get_Children_Sample {

public static void main(String[] args) throws Exception {

String path = "/zk-book";

 ZkClient zkClient = new  ZkClient("domain1.book.zookeeper:2181", 5000);

zkClient.subscribeChildChanges(path, new IZkChildListener() {

public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {

System.out.println(parentPath + " 's child changed, currentChilds:" + currentChilds);

}

});

zkClient.createPersistent(path);

Thread.sleep(1000);

System.out.println(zkClient.getChildren(path));

Thread.sleep(1000);

zkClient.createPersistent(path + "/c1");

Thread.sleep(1000);

zkClient.delete(path + "/c1");

Thread.sleep(1000);

zkClient.delete(path);

Thread.sleep(Integer.MAX_VALUE);

}

}

运行程序,输出结果如下:

在上面这个示例程序中,首先对/zk-book注册了IZkChildListener监听,此时该节点并不存在。当创建了/zk-book节点后,客户端立即会收到来自服务端的事件通知,当然此时接收到的子节点列表为null。然后继续创建节点/zk-book/c1,此时客户端就会收到子节点列表变更通知,同时收到最新的子节点列表为[c1]。随后,我们删除了/zk-book/c1节点,客户端同样会收到事件变更通知。最后,当将/zk-book节点本身删除的时候,客户端受到了事件通知,同时可以发现,此时子节点列表为null。

从上面的示例程序和输出结果中,我们可以得出以下3个结论。

  • 客户端可以对一个不存在的节点进行子节点变更的监听。
  • 一旦客户端对一个节点注册了子节点列表变更监听之后,那么当该节点的子节点列表发生变更的时候,服务端都会通知客户端,并将最新的子节点列表发送给客户端。
  • 该节点本身的创建或删除也会通知到客户端。
另外,还需要明确的一点是,和ZooKeeper原生提供的Watcher不同的是, ZkClient的LIstener不是一次性的,客户端只需要注册一次就会一直生效。

getData

在ZkClient中,可以通过以下API来获取指定节点的数据内容:
<T extends Object> T readData(String path)
<T extends Object> T readData(String path, boolean returnNullIfPathNotExists)
<T extends Object> T readData(String path, Stat stat)
该API方法的参数说明如下表所示。

参数名说明
returnNullIfPathNotExists默认情况下,在调用该API的时候,如果指定的节点不存在,那么会抛出异常:org.apache.zookeeper.KeeperException&NoNodeException。如果设置了这个参数,那么如果节点不存在,就直接返回null,而不会抛出异常
stat指定数据节点的节点状态信息。用法是在接口中传入一个旧的stat变量,该stat变量会在方法执行过程中,被来自服务端响应的新stat对象替换

通过调用这个接口,就可以获取指定节点的数据内容。注意,方法的返回值,在ZkClient内部已经被反序列化成指定对象。

另外,该接口对服务端事件的监听,同样是通过注册指定的Listener来实现的:

public interface IZkDataListener {

public void handleDataChange(String dataPath, Object data) throws Exception;

public void handleDataDeleted(String dataPath) throws Exception;

}

在这个Listener接口中,有两个接口方法handleDataChange和handleDataDeleted,用于处理服务端发来的两类事件通知,分别为“节点内容变更”和“节点删除”事件。该API方法的参数说明如下表所示。

参数名说明
dataPath事件通知对应的节点路径
data最新的数据内容

如果客户端对指定节点nodeA注册了IZkDataListener监听,那么将会接收到如下表所示的来自服务端的事件通知。

事件类型说明
节点数据变化指定节点nodeA的数据内容(content)或是数据版本(version)发生变更,都会触发这个事件。此时在handleDataChange方法中,dataPath收到的是nodeA的全路径,data是最新的数据节点内容
删除节点nodeA指定节点nodeA被删除。此时在handleDataDeleted方法中,dataPath收到的是nodeA的全路径

下面,我们通过实际代码来看看getData接口以及子节点列表变更监听的使用方式。

// 使用ZkClient获取节点数据内容

public class Get_Data_Sample {

public static void main(String[] args) throws Exception {

String path = "/zk-book";

 ZkClient zkClient = new  ZkClient("domain1.book.zookeeper:2181", 5000);

zkClient.createEphemeral(path, "123");

zkClient.subscribeDataChanges(path, new IZkDataListener() {

public void handleDataChange(String parentPath) throws Exception {

System.out.println("Node " + dataPath + " deleted.");

}

public void handleDataChange(String dataPath, Object data) throws Exception {

System.out.println("Node " + dataPath + "changed, new data:" + data);

}

});

System.out.println(zkClient.readData(path));

zkClient.writeData(path, "456");

Thread.sleep(1000);

zkClient.delete(path);

Thread.sleep(Integer.MAX_VALUE);

}

}

运行程序,输出结果如下:


在上面这个示例程序中,首先创建了节点/zk-book,并且调用readData接口来获取其数据内容,同时在该节点上注册了IZkDataListener监听,实现对该节点数据变更的监听。这样一来,之后凡是该节点数据变化或是该节点被删除,服务端都会向客户端发出事件通知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值