Java操作zookeeper总共有三种方式:

1.原生的Java API

2.zkclient

3.curator

第一种实现代码:

pom.xml

<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>

示例的java代码如下:

package zook;

import java.io.IOException;
import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs; public class App { public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String connStr = "192.168.126.128:2181";
CountDownLatch countDown = new CountDownLatch(1); Watcher watcher=new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getState() == KeeperState.SyncConnected) {
System.err.println("eventType:"+event.getType());
if(event.getType()==Event.EventType.None){
countDown.countDown();
}else if(event.getType()==Event.EventType.NodeCreated){
System.out.println("listen:节点创建");
}else if(event.getType()==Event.EventType.NodeChildrenChanged){
System.out.println("listen:子节点修改");
}
}
}
}; ZooKeeper zookeeper = new ZooKeeper(connStr, 5000,watcher );
countDown.await(); //注册监听,每次都要重新注册,否则监听不到
zookeeper.exists("/top/jinyong", watcher); // 创建节点
String result = zookeeper.create("/top/jinyong", "一生一世".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(result); Thread.sleep(10); // 获取节点
byte[] bs = zookeeper.getData("/top/jinyong", true, null);
result = new String(bs);
System.out.println("创建节点后的数据是:" + result); // 修改节点
zookeeper.setData("/top/jinyong", "I love you".getBytes(), -1); Thread.sleep(10); bs = zookeeper.getData("/top/jinyong", true, null);
result = new String(bs);
System.out.println("修改节点后的数据是:" + result); // 删除节点
zookeeper.delete("/top/jinyong", -1);
System.out.println("节点删除成功");
} }

说明:

1.会话连接是异步的,需要自己去处理。此处用的CountDownLatch

2.Watch需要重复注册,不然就不能生效,比如开始的zookeeper.exists("/top/jinyong", watcher);就是为了注册监听

3.开发的复杂性还是比较高的

4.不支持多节点删除和创建。需要自己去递归。后面有一个关于递归的示例。

第二种实现:

pom.xml

<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>

示例的Java代码如下:

package zook;

import java.util.List;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher.Event.KeeperState; public class Client { public static void main(String[] args) throws InterruptedException {
String connStr = "192.168.126.128:2181";
ZkClient zk = new ZkClient(connStr); // 注册【数据】事件
zk.subscribeDataChanges("/top/zhuzhu", new IZkDataListener() { @Override
public void handleDataDeleted(String arg0) throws Exception {
System.err.println("数据删除:" + arg0); } @Override
public void handleDataChange(String arg0, Object arg1) throws Exception {
System.err.println("数据修改:" + arg0 + "------" + arg1); }
}); zk.subscribeChildChanges("/top", new IZkChildListener() { @Override
public void handleChildChange(String arg0, List<String> arg1) throws Exception {
System.err.println("子节点发生变化:" + arg0);
arg1.forEach(f -> {
System.out.println("content:" + f);
});
}
}); List<String> list = zk.getChildren("/");
list.forEach(e -> {
System.out.println(e);
}); String res = zk.create("/top/zhuzhu", "I love you", CreateMode.PERSISTENT);
System.out.println("创建节点/top/zhuzhu成功:" + res); zk.writeData("/top/zhuzhu", "forerver");
System.out.println("修改节点/top/zhuzhu数据成功"); res = zk.readData("/top/zhuzhu");
System.out.println("节点数据:" + res); Thread.sleep(1000); zk.delete("/top/zhuzhu");
System.out.println("删除节点/top/zhuzhu成功"); Thread.sleep(1000); System.out.println("------------------------------------------------"); for (int i = 0; i < 10; i++) {
zk.create("/top/zhuzhu", "I love you", CreateMode.PERSISTENT);
Thread.sleep(1000);
zk.delete("/top/zhuzhu");
Thread.sleep(1000);
} } }

说明:

1.subscribe开头的为注册监听的一些方法

2.addAuthInfo和setAcl为权限相关控制

3.普通使用这种方式还是值得推荐的

第三种实现:

pom.xml

<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.11.0</version>
</dependency>

示例的Java代码如下:

package zook;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat; public class Curator { public static void main(String[] args) throws Exception {
String connStr = "192.168.23.24:2181";
CuratorFramework cur=CuratorFrameworkFactory.builder()
.connectString(connStr)
.connectionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.build();
cur.start();//连接 //创建监听
PathChildrenCache cache=new PathChildrenCache(cur,"/top",true);
cache.start();
cache.rebuild();
cache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework framwork, PathChildrenCacheEvent event) throws Exception {
System.err.println("节点发生变化:"+event.getType());
}
}); Stat stat=cur.checkExists().forPath("/top/zhuzhu");
if(stat!=null){
System.out.println("【/top/zhuzhu】节点存在,直接删除");
cur.delete().forPath("/top/zhuzhu");
}
cur.delete().forPath("/top/zhuzhu"); System.in.read(); System.out.println("准备创建【/top/zhuzhu】");
cur.create().withMode(CreateMode.PERSISTENT)
.forPath("/top/zhuzhu", "love forever".getBytes());
System.out.println("节点【/top/zhuzhu】创建成功"); Thread.sleep(1000); byte[] bs=cur.getData().forPath("/top/zhuzhu");
System.out.println("数据:"+new String(bs)); Thread.sleep(1000); cur.delete().forPath("/top/zhuzhu"); Thread.sleep(1000); } /**
* 三种watcher来做节点的监听
* pathcache 监视一个路径下子节点的创建、删除、节点数据更新
* NodeCache 监视一个节点的创建、更新、删除
* TreeCache pathcaceh+nodecache 的合体(监视路径下的创建、更新、删除事件),
* 缓存路径下的所有子节点的数据
*/ public static void main1(String[] args) throws Exception {
String connStr = "192.168.23.24:2181";
CuratorFramework curatorFramework=CuratorFrameworkFactory.builder()
.connectString(connStr)
.connectionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.build();
curatorFramework.start(); /**
* 节点变化NodeCache
*/
/* NodeCache cache=new NodeCache(curatorFramework,"/curator",false);
cache.start(true); cache.getListenable().addListener(()-> System.out.println("节点数据发生变化,变化后的结果" +
":"+new String(cache.getCurrentData().getData()))); curatorFramework.setData().forPath("/curator","菲菲".getBytes());*/ /**
* PatchChildrenCache
*/ PathChildrenCache cache=new PathChildrenCache(curatorFramework,"/event",true);
cache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
cache.rebuild();
// Normal / BUILD_INITIAL_CACHE /POST_INITIALIZED_EVENT cache.getListenable().addListener((curatorFramework1,pathChildrenCacheEvent)->{
switch (pathChildrenCacheEvent.getType()){
case CHILD_ADDED:
System.out.println("增加子节点");
break;
case CHILD_REMOVED:
System.out.println("删除子节点");
break;
case CHILD_UPDATED:
System.out.println("更新子节点");
break;
default:break;
}
}); // curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event","event".getBytes());
// TimeUnit.SECONDS.sleep(1);
// System.out.println("1");
// curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/event/event1","1".getBytes());
// TimeUnit.SECONDS.sleep(1);
// System.out.println("2");
//
// curatorFramework.setData().forPath("/event/event1","222".getBytes());
// TimeUnit.SECONDS.sleep(1);
// System.out.println("3"); curatorFramework.delete().forPath("/event/event1");
System.out.println("4"); System.in.read(); } }

说明:

1.支持事务

2.支持Flush写法

3.开始测试多次程序启动就执行删除节点,而监听的结果确实新增,后来加了cache.rebuild();代码就没问题了。跟源码,在cache.start()里面有一个构造函数也是调用了rebuild方法的。

4.功能还是比较强大的。高级功能都会用到这种方式

最后贴一个原生API的递归操作方式:

package zook;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs; public class ZookManager {
ZooKeeper zookeeper = null; public ZookManager(String connStr) throws IOException, InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
zookeeper = new ZooKeeper(connStr, 5000, new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getType() == EventType.None) {
if (event.getState() == KeeperState.SyncConnected) {
latch.countDown();
} else {
System.out.println("连接失败.");
latch.countDown();
}
}
} });
latch.await();
} /** 创建节点,不存在父节点将新增,如果节点已经存在将抛出异常 **/
public String create(String path, String val) throws KeeperException, InterruptedException {
if (!checkPath(path)) {
return "";
} String p = getParentPath(path);
cycleCreate(p); String url = zookeeper.create(path, val.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
return url;
} /** 设置节点的数据,如果节点不存在将新增该节点 **/
public Stat setData(String path, String val) throws KeeperException, InterruptedException {
if (!checkPath(path)) {
return null;
} cycleCreate(path);
return zookeeper.setData(path, val.getBytes(), -1);
} /** 删除节点,如果存在子节点将递归删除
* @throws InterruptedException
* @throws KeeperException **/
public void delete(String path) throws KeeperException, InterruptedException {
if (!checkPath(path)) {
return;
} List<String> chidren = zookeeper.getChildren(path, false);
for (String p : chidren) {
delete(path + "/" + p);
}
zookeeper.delete(path, -1);
} private void cycleCreate(String path) throws KeeperException, InterruptedException {
Stat stat = zookeeper.exists(path, null);
if (stat == null) {
String p = getParentPath(path);
cycleCreate(p);// 递归
// 创建
zookeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
} /**
* 检查目录是否正确
* @param path
* @return
*/
private boolean checkPath(String path) {
if (!path.startsWith("/")) {
System.err.println("路径必须以/开头:" + path);
return false;
}
if (path.endsWith("/")) {
System.err.println("路径不能以/结尾:" + path);
return false;
}
if (path.contains("//")) {
System.err.println("路径格式不对,存在连续的/:" + path);
return false;
}
if (path.equals("/")) {
System.err.println("路径格式不对,只有一个/:" + path);
return false;
}
return true;
} /**
* 获得父级目录
* @param path /root/abc
* @return
*/
private String getParentPath(String path) {
int index = path.lastIndexOf("/");
return path.substring(0, index);
} public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZookManager zoo = new ZookManager("192.168.23.24:2181");
zoo.setData("/top/enjoy/abc", "abc");
zoo.setData("/top/enjoy/bbb", "bbb");
zoo.setData("/top/enjoy/ccc", "ccc");
System.out.println("成功新增");
zoo.delete("/top/enjoy");
System.out.println("成功删除");
}
}

Java操作zookeeper的更多相关文章

  1. java 操作zookeeper

    java 操作zookeeper(一) 首先要使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper ...

  2. zookeeper(三):java操作zookeeper

    引入jar包 首先要使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper-3.4.5.jar 和 ...

  3. Java 使用ZkClient操作Zookeeper

    目录 ZkClient介绍 导入jar包依赖 简单使用样例 ZkClient介绍 因为Zookeeper API比较复杂,使用并不方便,所以出现了ZkClient,ZkClient对Zookeeper ...

  4. Java代码操作zookeeper

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  5. Zookeeper--java操作zookeeper

    如果是使用java操作zookeeper,zookeeper的javaclient 使我们更轻松的去对zookeeper进行各种操作,我们引入zookeeper-3.4.5.jar 和 zkclien ...

  6. Zookeeper入门(七)之Java连接Zookeeper

    Java操作Zookeeper很简单,但是前提要把包导对. 关于Zookeeper的Linux环境搭建可以参考我的这篇博客:Linux环境下Zookeeper安装 下面进入正题: 一.导入依赖 < ...

  7. Java curator操作zookeeper获取kafka

    Java curator操作zookeeper获取kafka Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更 ...

  8. Hbase深入学习(六) Java操作HBase

    Hbase深入学习(六) ―― Java操作HBase 本文讲述如何用hbase shell命令和hbase java api对hbase服务器进行操作. 先看以下读取一行记录hbase是如何进行工作 ...

  9. Java操作hbase总结

    用过以后,总得写个总结,不然,就忘喽. 一.寻找操作的jar包. java操作hbase,首先要考虑到使用hbase的jar包. 因为咱装的是CDH5,比较方便,使用SecureCRT工具,远程连接到 ...

随机推荐

  1. 识别简单的答题卡(Bubble sheet multiple choice scanner and test grader using OMR, Python and OpenCV——jsxyhelu重新整编)

    该博客转自www.pyimagesearch.com,进行了相关修改补充. Over the past few months I've gotten quite the number of reque ...

  2. JavaScript中this的用法 及 如何改变this的指向

    要懂得JavaScript中this的用法,首先需要知道,JavaScript中的作用域相关知识. var fun = function(){ var flag = 1; console.log(fl ...

  3. linux tmux 工具使用 tmux.conf 文件

    set -g prefix ^a unbind ^b bind a send-prefix unbind '"' bind - splitw -v unbind % bind \ split ...

  4. iOS开发 -------- UITableView的编辑

    一 核心API Class: UITableView Delegate: UITableViewDataSource, UITableViewDelegate 涉及到的API: 插入和删除 1 /** ...

  5. FireMonkey 源码学习(3)

    五.TTextLayoutNG 在FMX.TextLayout.GPU.pas文件中,实现了几个基础功能,其中: (1)渲染单元 在TextLayout中,每一批同字体和颜色的1~n个字符,组成一个最 ...

  6. C# Math类简介运用

    总结了一下几个常用的Math类 /* ######### ############ ############# ## ########### ### ###### ##### ### ####### ...

  7. word2010使用记录

    安装时提示: installer无法更新被保护的一个或多个文件, 解决方法是: 将三个dll文件,放在 c:\program files\common files\ms shared\web serv ...

  8. Docker 使用Dockerfile构建tomcat镜像

    Dockerfile概念: 镜像的定制实际上就是定制每一层所添加的配置.文件.如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像,那么之前提及的无法重复的问题. ...

  9. P2221 [HAOI2012]高速公路

    思路 考虑每一条边的贡献,然后推式子 \[ \begin{align}&\sum_{i}V_i\times(R-i+1)\times(i-L+1)\\=&\sum_{i}V_i\lef ...

  10. Vue学习四:v-if及v-show指令使用方法

    本文为博主原创,未经允许不得转载: <!DOCTYPE html> <html lang="zh"> <head> <meta http- ...