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方法的参数说明如下表所示。
如果客户端对指定节点nodeA注册了IZkChildListener监听,那么将会接收到如下表所示的事件通知。
参数名 说明 parentPath 子节点变更通知对应的父节点的节点路径 currentChilds 子节点的相对路径列表,如果没有子节点,那么会传入null
下面,我们通过实际代码来看看getChildren接口以及子节点列表变更监听的使用方式。
事件类别 说明 新增子节点 指定节点nodeA新增子节点。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是最新的子节点列表(相对路径) 减少子节点 指定节点nodeA减少子节点。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是最新的子节点列表(相对路径),可能是null 删除节点nodeA 指定节点nodeA被删除。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是null
// 使用 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个结论。
- 客户端可以对一个不存在的节点进行子节点变更的监听。
- 一旦客户端对一个节点注册了子节点列表变更监听之后,那么当该节点的子节点列表发生变更的时候,服务端都会通知客户端,并将最新的子节点列表发送给客户端。
- 该节点本身的创建或删除也会通知到客户端。
getData
参数名 说明 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方法的参数说明如下表所示。
如果客户端对指定节点nodeA注册了IZkDataListener监听,那么将会接收到如下表所示的来自服务端的事件通知。
参数名 说明 dataPath 事件通知对应的节点路径 data 最新的数据内容
下面,我们通过实际代码来看看getData接口以及子节点列表变更监听的使用方式。
事件类型 说明 节点数据变化 指定节点nodeA的数据内容(content)或是数据版本(version)发生变更,都会触发这个事件。此时在handleDataChange方法中,dataPath收到的是nodeA的全路径,data是最新的数据节点内容 删除节点nodeA 指定节点nodeA被删除。此时在handleDataDeleted方法中,dataPath收到的是nodeA的全路径
// 使用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监听,实现对该节点数据变更的监听。这样一来,之后凡是该节点数据变化或是该节点被删除,服务端都会向客户端发出事件通知。