在 ZooKeeper 类中,我们可以通过 getChildren 方法获取指定节点的子节点列表。
List<String> getChildren(String path, boolean watch) 返回给定路径节点的子节点列表。如果 watch 为 true 且调用成功(无异常抛出),则会监听给定路径节点。如果删除给定路径的节点或在该节点下创建/删除子节点的操作成功,则会触发监视。返回的子节点列表不排序,也不保证其自然顺序或词法顺序。如果不存在具有给定路径的节点,将抛出错误代码为 KeeperException.NoNode 的 KeeperException。
void getChildren(String path, boolean watch, AsyncCallback.Children2Callback cb, Object ctx) 方法异步版本。
void getChildren(String path, boolean watch, AsyncCallback.ChildrenCallback cb, Object ctx) 方法异步版本。
List<String> getChildren(String path, boolean watch, Stat stat) 返回给定 znode 路径的状态和子节点列表。
List<String> getChildren(String path, Watcher watcher) 返回给定路径节点的子节点列表。
void getChildren(String path, Watcher watcher, AsyncCallback.Children2Callback cb, Object ctx) 异步版本。
void getChildren(String path, Watcher watcher, AsyncCallback.ChildrenCallback cb, Object ctx) 异步版本。
List<String> getChildren(String path, Watcher watcher, Stat stat) 返回给定 znode 路径的状态和子节点列表。
参数说明:
path - 节点路径
watch - 是否给节点添加监听,如果设置为 true,则修改/删除节点时将会触发节点上注册的监听器
cb - 回调接口
ctx - 上下文对象,用于向回调接口传递扩展数据
stat - 状态对象,获取对象数据后,会将节点状态设置到该对象中
watcher - 监听器,直接给节点注册监听器
该示例演示如何通过 ZooKeeper 类的 getChildren 方法获取指定节点的子节点列表,代码如下:
package com.hxstrive.zookeeper; import com.alibaba.fastjson.JSONObject; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import org.junit.Before; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; /** * 获取节点子节点列表 * @author hxstrive.com */ public class GetChildrenNode { private static ZooKeeper zooKeeper; @Before public void init() throws Exception { zooKeeper = new ZooKeeper("127.0.0.1:2181", 2000, new Watcher() { public void process(WatchedEvent watchedEvent) { System.out.println("触发了 " + watchedEvent.getType() + " 事件"); } }); // 如果节点不存在,则创建节点,初始化数据 createNode("/getChildren_node", "getChildren节点数据"); createNode("/getChildren_node/books", "书籍列表"); createNode("/getChildren_node/books/java", "《Java编程》"); createNode("/getChildren_node/books/c#", "《C#编程》"); createNode("/getChildren_node/books/c++", "《C++编程》"); createNode("/getChildren_node/jobs", "工作集合"); createNode("/getChildren_node/jobs/chef", "厨师"); createNode("/getChildren_node/jobs/teacher", "教师"); } private void createNode(String path, String data) throws Exception { Stat stat = zooKeeper.exists(path, false); if(null == stat) { // 节点不存在,创建该节点 String nodeName = zooKeeper.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("成功创建 " + nodeName + " 节点"); } } /** * 同步获取节点子节点列表 */ @Test public void syncDemo() throws Exception { // 注册监听器 zooKeeper.register(new Watcher() { @Override public void process(WatchedEvent watchedEvent) { System.out.println("监听器 " + JSONObject.toJSONString(watchedEvent)); } }); // 获取 /getChildren_node 节点的子节点列表,且监听该节点 // 注意:这里只会获取到 /getChildren_node 节点的直接子节点,不会获取子节点的子节点 List<String> nodeList = zooKeeper.getChildren("/getChildren_node", true); System.out.println("子节点:" + Arrays.toString(nodeList.toArray())); // 创建一个子节点触发监听器 createNode("/getChildren_node/tmp", "temp"); Thread.sleep(1000); //输出: //触发了 None 事件 //成功创建 /getChildren_node/books 节点 //... //子节点:[books, jobs] //成功创建 /getChildren_node/tmp 节点 //监听器 {"path":"/getChildren_node","state":"SyncConnected","type":"NodeChildrenChanged", // "wrapper":{"path":"/getChildren_node","state":3,"type":4}} } @Test public void syncDemo2() throws Exception { // 获取 /getChildren_node 节点的子节点列表,且监听该节点 // 注意:这里只会获取到 /getChildren_node 节点的直接子节点,不会获取子节点的子节点 List<String> nodeList = zooKeeper.getChildren("/getChildren_node", new Watcher() { @Override public void process(WatchedEvent watchedEvent) { System.out.println("监听器 " + JSONObject.toJSONString(watchedEvent)); } }); System.out.println("子节点:" + Arrays.toString(nodeList.toArray())); // 创建一个子节点触发监听器 createNode("/getChildren_node/tmp", "temp"); Thread.sleep(1000); //输出: //触发了 None 事件 //子节点:[books, jobs] //成功创建 /getChildren_node/tmp 节点 //监听器 {"path":"/getChildren_node","state":"SyncConnected","type":"NodeChildrenChanged", // "wrapper":{"path":"/getChildren_node","state":3,"type":4}} } /** * 异步获取节点子节点列表 */ @Test public void asyncDemo() throws Exception { CountDownLatch countDownLatch = new CountDownLatch(2); // 获 /getChildren_node 节点的取子节点列表 // 采用 AsyncCallback.Children2Callback 回调接口,processResult 方法多了一个 stat 节点状态 zooKeeper.getChildren("/getChildren_node", false, new AsyncCallback.Children2Callback() { @Override public void processResult(int i, String s, Object o, List<String> list, Stat stat) { System.out.println("Children2Callback.i = " + i); System.out.println("Children2Callback.s = " + s); System.out.println("Children2Callback.list = " + Arrays.toString(list.toArray())); System.out.println("Children2Callback.stat = " + JSONObject.toJSONString(stat)); countDownLatch.countDown(); } }, "扩展数据1"); // 采用 AsyncCallback.ChildrenCallback 回调接口 zooKeeper.getChildren("/getChildren_node", false, new AsyncCallback.ChildrenCallback() { @Override public void processResult(int i, String s, Object o, List<String> list) { System.out.println("ChildrenCallback.i = " + i); System.out.println("ChildrenCallback.s = " + s); System.out.println("ChildrenCallback.list = " + Arrays.toString(list.toArray())); countDownLatch.countDown(); } }, "扩展数据2"); countDownLatch.await(); //输出: //触发了 None 事件 //Children2Callback.i = 0 //Children2Callback.s = /getChildren_node //Children2Callback.list = [books, tmp, jobs] //Children2Callback.stat = {"aversion":0,"ctime":1704011838603,"cversion":7,"czxid":249,"dataLength":8, // "ephemeralOwner":0,"mtime":1704011838718,"mzxid":257,"numChildren":3,"pzxid":287,"version":1} //ChildrenCallback.i = 0 //ChildrenCallback.s = /getChildren_node //ChildrenCallback.list = [books, tmp, jobs] } }