客户端可以通过 ZooKeeper 的 API 来读取节点内容,有如下四个接口:
public byte[] getData(final String path, Watcher watcher, Stat stat)
public byte[] getData(String path, boolean watch, Stat stat)
public void getData(final String path, Watcher watcher, DataCallback cb, Object ctx)
public void getData(String path, boolean watch, DataCallback cb, Object ctx)
这两个接口分别以同步
和异步
方式读取节点内容,API 方法的参数说明如表:
参数名 | 说明 |
---|---|
path | 指定数据节点的路径,获取该节点内容。 |
watcher | 注册在path上的Watcher。节点变更会通知会向客户端发起通知。 |
stat | 指定数据节点状态信息。传入旧stat,方法执行过程中会将其替换为新stat对象。 |
watch | 表示是否需要注册一个watcher。true:注册默认watcher,false:不需要注册watcher。 |
cb | 注册一个异步回调函数。 |
ctx | 传递上下文信息。 |
使用同步API读取节点内容
package com.lpf.zookeeper.ZooKeeper.getData;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.CountDownLatch;
/**
* 读取节点数据
*/
public class TestGetDataSync implements Watcher {
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception {
zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, new TestGetData());
countDownLatch.await();
String path = "/test-get-data";
zooKeeper.create(path, "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("同步读取节点内容:" + new String(zooKeeper.getData(path, true, stat)));
System.out.println("同步读取Stat:czxid=" + stat.getCzxid() + ";mzxid=" + stat.getMzxid() + ";version=" + stat.getVersion());
zooKeeper.setData(path, "123".getBytes(), -1);
Thread.sleep(10000);
}
public void process(WatchedEvent event) {
if (Event.KeeperState.SyncConnected == event.getState()) {
if (Event.EventType.None == event.getType() && null == event.getPath()) { // 连接时的监听事件
countDownLatch.countDown();
} else if (event.getType() == Event.EventType.NodeDataChanged) { // 子节点内容变更时的监听
try {
System.out.println("监听获得通知内容:data=" + new String(zooKeeper.getData(event.getPath(), true, stat)));
System.out.println("监听获得通知Stat:czxid=" + stat.getCzxid() + ";mzxid=" + stat.getMzxid() + ";version=" + stat.getVersion());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
运行程序,输出结果如下:
同步读取节点内容:123
同步读取Stat:czxid=55;mzxid=55;version=0
监听获得通知内容:data=123
监听获得通知Stat:czxid=55;mzxid=56;version=1
代码的基本逻辑为创建一个临时节点,然后读取临时节点内容,并注册监听,当节点变化(内容变化或版本信息变化),触发监听事件,获取最新的节点信息。
使用异步API读取节点内容
package com.lpf.zookeeper.ZooKeeper.getData;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.CountDownLatch;
/**
* 读取节点数据
*/
public class TestGetDataASync implements Watcher {
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception {
zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, new TestGetDataASync());
countDownLatch.await();
String path = "/test-get-data";
zooKeeper.create(path, "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
// 异步读取节点内容
zooKeeper.getData(path, true, new MyDataCallback(), null);
zooKeeper.setData(path, "123".getBytes(), -1);
Thread.sleep(10000);
}
public void process(WatchedEvent event) {
if (Event.KeeperState.SyncConnected == event.getState()) {
if (Event.EventType.None == event.getType() && null == event.getPath()) { // 连接时的监听事件
countDownLatch.countDown();
} else if (event.getType() == Event.EventType.NodeDataChanged) { // 子节点内容变更时的监听
try {
System.out.println("监听获得通知内容:data=" + new String(zooKeeper.getData(event.getPath(), true, stat)));
System.out.println("监听获得通知Stat:czxid=" + stat.getCzxid() + ";mzxid=" + stat.getMzxid() + ";version=" + stat.getVersion());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
class MyDataCallback implements AsyncCallback.DataCallback {
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
System.out.println("异步返回结果:rc=" + rc + ";path=" + path + ";data=" + new String(data));
System.out.println("异步读取Stat:czxid=" + stat.getCzxid()
+ ";mzxid=" + stat.getMzxid() + ";version=" + stat.getVersion());
}
}
运行程序,输出结果如下:
异步返回结果:rc=0;path=/test-get-data;data=123
异步读取Stat:czxid=60;mzxid=60;version=0
监听获得通知内容:data=123
监听获得通知Stat:czxid=60;mzxid=61;version=1
异步方法与同步方法业务逻辑基本相同,区别点在于将同步获取改为异步获取。