WatcherZK状态事件类型 ,权限
Posted 小~虎
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WatcherZK状态事件类型 ,权限相关的知识,希望对你有一定的参考价值。
zookeeper有watch事件,是一次性触发的,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher。
同样,其watcher是监听数据发送了某些变化,那就一定会有对应的事件类型和状态类型。
事件类型:(znode节点相关的)
EventType.NodeCreated
EventType.NodeDataChanged
EventType.NodeChildrenChanged
EventType.NodeDeleted
状态类型:(跟客户端实例相关的)
keeperState.Disconnected
keeperState.SyncConnected
keeperState.AuthFailed
keeperState.Expired
watcher的特性:一次性、客户端串行执行、轻量
一次性:对于ZK的watcher,只需要记住一点:zookeeper有watch事件,是一次性触发的,当watch监视的数据发生变化时,通知设置了该watch的client,即watcher,由于zookeeper的监控都是一次性的,所以每次必须设置监控。
客户端串行执行:客户端Watcher回调的过程是一个串行同步的过程,这为我们保证了顺序,同事需要开发人员注意一点,千万不要因为一个Watcher的处理逻辑影响了整个客户端的Watcher回调。
轻量:WatchedEvent 是Zookeeper整个Watcher通知机制的最小通知单元,整个结构只包含三部分:通知状态、事件类型和节点路径。也就是说Watcher通知非常的简单,只会告诉客户端发生了事件,而不会告知其具体内容,需要客户端自己去进行获取,比如NodeDataChanged事件,Zookeeper只会通知客户端指定节点的数据发生了变更,而不会直接提供具体的数据内容。
1 package bjsxt.zookeeper.watcher; 2 3 import java.util.List; 4 import java.util.concurrent.CountDownLatch; 5 import java.util.concurrent.atomic.AtomicInteger; 6 7 import org.apache.zookeeper.CreateMode; 8 import org.apache.zookeeper.WatchedEvent; 9 import org.apache.zookeeper.Watcher; 10 import org.apache.zookeeper.Watcher.Event.EventType; 11 import org.apache.zookeeper.Watcher.Event.KeeperState; 12 import org.apache.zookeeper.ZooDefs.Ids; 13 import org.apache.zookeeper.ZooKeeper; 14 import org.apache.zookeeper.data.Stat; 15 16 /** 17 * Zookeeper Wathcher 18 * 本类就是一个Watcher类(实现了org.apache.zookeeper.Watcher类) 19 * @author(alienware) 20 * @since 2015-6-14 21 */ 22 public class ZooKeeperWatcher implements Watcher { 23 24 /** 定义原子变量 */ 25 AtomicInteger seq = new AtomicInteger(); 26 /** 定义session失效时间 */ 27 private static final int SESSION_TIMEOUT = 10000; 28 /** zookeeper服务器地址 */ 29 private static final String CONNECTION_ADDR = "192.168.80.88:2181"; 30 /** zk父路径设置 */ 31 private static final String PARENT_PATH = "/testWatch"; 32 /** zk子路径设置 */ 33 private static final String CHILDREN_PATH = "/testWatch/children"; 34 /** 进入标识 */ 35 private static final String LOG_PREFIX_OF_MAIN = "【Main】"; 36 /** zk变量 */ 37 private ZooKeeper zk = null; 38 /** 信号量设置,用于等待zookeeper连接建立之后 通知阻塞程序继续向下执行 */ 39 private CountDownLatch connectedSemaphore = new CountDownLatch(1); 40 41 /** 42 * 创建ZK连接 43 * @param connectAddr ZK服务器地址列表 44 * @param sessionTimeout Session超时时间 45 */ 46 public void createConnection(String connectAddr, int sessionTimeout) { 47 this.releaseConnection(); 48 try { 49 zk = new ZooKeeper(connectAddr, sessionTimeout, this); 50 System.out.println(LOG_PREFIX_OF_MAIN + "开始连接ZK服务器"); 51 connectedSemaphore.await(); 52 } catch (Exception e) { 53 e.printStackTrace(); 54 } 55 } 56 57 /** 58 * 关闭ZK连接 59 */ 60 public void releaseConnection() { 61 if (this.zk != null) { 62 try { 63 this.zk.close(); 64 } catch (InterruptedException e) { 65 e.printStackTrace(); 66 } 67 } 68 } 69 70 /** 71 * 创建节点 72 * @param path 节点路径 73 * @param data 数据内容 74 * @return 75 */ 76 public boolean createPath(String path, String data) { 77 try { 78 //设置监控(由于zookeeper的监控都是一次性的所以 每次必须设置监控) 79 this.zk.exists(path, true); 80 System.out.println(LOG_PREFIX_OF_MAIN + "节点创建成功, Path: " + 81 this.zk.create( /**路径*/ 82 path, 83 /**数据*/ 84 data.getBytes(), 85 /**所有可见*/ 86 Ids.OPEN_ACL_UNSAFE, 87 /**永久存储*/ 88 CreateMode.PERSISTENT ) + 89 ", content: " + data); 90 } catch (Exception e) { 91 e.printStackTrace(); 92 return false; 93 } 94 return true; 95 } 96 97 /** 98 * 读取指定节点数据内容 99 * @param path 节点路径 100 * @return 101 */ 102 public String readData(String path, boolean needWatch) { 103 try { 104 return new String(this.zk.getData(path, needWatch, null)); 105 } catch (Exception e) { 106 e.printStackTrace(); 107 return ""; 108 } 109 } 110 111 /** 112 * 更新指定节点数据内容 113 * @param path 节点路径 114 * @param data 数据内容 115 * @return 116 */ 117 public boolean writeData(String path, String data) { 118 try { 119 System.out.println(LOG_PREFIX_OF_MAIN + "更新数据成功,path:" + path + ", stat: " + 120 this.zk.setData(path, data.getBytes(), -1)); 121 } catch (Exception e) { 122 e.printStackTrace(); 123 } 124 return false; 125 } 126 127 /** 128 * 删除指定节点 129 * 130 * @param path 131 * 节点path 132 */ 133 public void deleteNode(String path) { 134 try { 135 this.zk.delete(path, -1); 136 System.out.println(LOG_PREFIX_OF_MAIN + "删除节点成功,path:" + path); 137 } catch (Exception e) { 138 e.printStackTrace(); 139 } 140 } 141 142 /** 143 * 判断指定节点是否存在 144 * @param path 节点路径 145 */ 146 public Stat exists(String path, boolean needWatch) { 147 try { 148 return this.zk.exists(path, needWatch); 149 } catch (Exception e) { 150 e.printStackTrace(); 151 return null; 152 } 153 } 154 155 /** 156 * 获取子节点 157 * @param path 节点路径 158 */ 159 private List<String> getChildren(String path, boolean needWatch) { 160 try { 161 return this.zk.getChildren(path, needWatch); 162 } catch (Exception e) { 163 e.printStackTrace(); 164 return null; 165 } 166 } 167 168 /** 169 * 删除所有节点 170 */ 171 public void deleteAllTestPath() { 172 if(this.exists(CHILDREN_PATH, false) != null){ 173 this.deleteNode(CHILDREN_PATH); 174 } 175 if(this.exists(PARENT_PATH, false) != null){ 176 this.deleteNode(PARENT_PATH); 177 } 178 } 179 180 /** 181 * 收到来自Server的Watcher通知后的处理。 182 */ 183 @Override 184 public void process(WatchedEvent event) { 185 186 System.out.println("进入 process 。。。。。event = " + event); 187 188 try { 189 Thread.sleep(200); 190 } catch (InterruptedException e) { 191 e.printStackTrace(); 192 } 193 194 if (event == null) { 195 return; 196 } 197 198 // 连接状态 199 KeeperState keeperState = event.getState(); 200 // 事件类型 201 EventType eventType = event.getType(); 202 // 受影响的path 203 String path = event.getPath(); 204 205 String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】"; 206 207 System.out.println(logPrefix + "收到Watcher通知"); 208 System.out.println(logPrefix + "连接状态:\t" + keeperState.toString()); 209 System.out.println(logPrefix + "事件类型:\t" + eventType.toString()); 210 211 if (KeeperState.SyncConnected == keeperState) { 212 // 成功连接上ZK服务器 213 if (EventType.None == eventType) { 214 System.out.println(logPrefix + "成功连接上ZK服务器"); 215 connectedSemaphore.countDown(); 216 } 217 //创建节点 218 else if (EventType.NodeCreated == eventType) { 219 System.out.println(logPrefix + "节点创建"); 220 try { 221 Thread.sleep(100); 222 } catch (InterruptedException e) { 223 e.printStackTrace(); 224 } 225 this.exists(path, true); 226 } 227 //更新节点 228 else if (EventType.NodeDataChanged == eventType) { 229 System.out.println(logPrefix + "节点数据更新"); 230 System.out.println("我看看走不走这里........"); 231 try { 232 Thread.sleep(100); 233 } catch (InterruptedException e) { 234 e.printStackTrace(); 235 } 236 System.out.println(logPrefix + "数据内容: " + this.readData(PARENT_PATH, true)); 237 } 238 //更新子节点 239 else if (EventType.NodeChildrenChanged == eventType) { 240 System.out.println(logPrefix + "子节点变更"); 241 try { 242 Thread.sleep(3000); 243 } catch (InterruptedException e) { 244 e.printStackTrace(); 245 } 246 System.out.println(logPrefix + "子节点列表:" + this.getChildren(PARENT_PATH, true)); 247 } 248 //删除节点 249 else if (EventType.NodeDeleted == eventType) { 250 System.out.println(logPrefix + "节点 " + path + " 被删除"); 251 } 252 else ; 253 } 254 else if (KeeperState.Disconnected == keeperState) { 255 System.out.println(logPrefix + "与ZK服务器断开连接"); 256 } 257 else if (KeeperState.AuthFailed == keeperState) { 258 System.out.println(logPrefix + "权限检查失败"); 259 } 260 else if (KeeperState.Expired == keeperState) { 261 System.out.println(logPrefix + "会话失效"); 262 } 263 else ; 264 265 System.out.println("--------------------------------------------"); 266 267 } 268 269 /** 270 * <B>方法名称:</B>测试zookeeper监控<BR> 271 * <B>概要说明:</B>主要测试watch功能<BR> 272 * @param args 273 * @throws Exception 274 */ 275 public static void main(String[] args) throws Exception { 276 277 //建立watcher 278 ZooKeeperWatcher zkWatch = new ZooKeeperWatcher(); 279 //创建连接 280 zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT); 281 //System.out.println(zkWatch.zk.toString()); 282 283 Thread.sleep(1000); 284 285 // 清理节点 286 zkWatch.deleteAllTestPath(); 287 288 if (zkWatch.createPath(PARENT_PATH, System.currentTimeMillis() + "")) { 289 290 Thread.sleep(1000); 291 292 293 // 读取数据 294 System.out.println("---------------------- read parent ----------------------------"); 295 //zkWatch.readData(PARENT_PATH, true); 296 297 // 读取子节点 298 System.out.println("---------------------- read children path ----------------------------"); 299 zkWatch.getChildren(PARENT_PATH, true); 300 301 // 更新数据 302 zkWatch.writeData(PARENT_PATH, System.currentTimeMillis() + ""); 303 304 Thread.sleep(1000); 305 306 // 创建子节点 307 zkWatch.createPath(CHILDREN_PATH, System.currentTimeMillis() + ""); 308 309 Thread.sleep(1000); 310 311 zkWatch.writeData(CHILDREN_PATH, System.currentTimeMillis() + ""); 312 } 313 314 Thread.sleep(50000); 315 // 清理节点 316 zkWatch.deleteAllTestPath(); 317 Thread.sleep(1000); 318 zkWatch.releaseConnection(); 319 } 320 321 }
zookeeper的ACL (AUTH)
ACL(Access Control List),Zookeeper作为一个分布式协调框架,其内部存储的都是一些关乎分布式系统运行时状态的元数据,尤其是涉及到一些分布式锁、Master选举和协调等应用场景。我们需要有效地保障Zookeeper中的数据安全,Zookeeper提供一套完善的ACL权限控制机制来保障数据的安全。
ZK提供了三种模式。权限模式,授权对象,权限。
权限模式:Scheme,开发人员最多使用一下四种权限模式:
IP:ip模式通过ip地址粒度来进行控制权限,例如配置了:ip:192.168.1.109即表示权限控制都是针对这个ip地址的,同时也支持按网段分配,比如192.168.1.*
Digest:digest是最常用的权限控制模式,也更符合我们对权限控制的认识,其类似于“username:password” 形式的权限标识进行权限配置,ZK会对形成的权限标识先后进行两次编码处理,分别是SHA-1加密算法、BASE64编码。
World:World是一直最开放的全校性控制模式,这种模式可以看作为特殊的Digest,他仅仅是一个标识而已。
Super:超级用户模式,在超级用户模式下可以对ZK任意进行操作
权限对象:指的是权限赋予的用户或者一个指定的实体,例如ip地址或机器等,在不同的模式下,授权对象是不同的,这种模式和权限对象一一对应。
权限:权限就是指那些通过权限检测后可以被允许执行的操作,在ZK中,对数据的操作权限分为以下五大类:
CREATE,DELLETE,READ,WRITE,ADMIN
1 package bjsxt.zookeeper.auth; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.concurrent.CountDownLatch; 6 import java.util.concurrent.atomic.AtomicInteger; 7 8 import org.apache.zookeeper.CreateMode; 9 import org.apache.zookeeper.WatchedEvent; 10 import org.apache.zookeeper.Watcher; 11 import org.apache.zookeeper.Watcher.Event.EventType; 12 import org.apache.zookeeper.Watcher.Event.KeeperState; 13 import org.apache.zookeeper.ZooDefs.Ids; 14 import org.apache.zookeeper.ZooKeeper; 15 import org.apache.zookeeper.data.ACL; 16 import org.apache.zookeeper.data.Stat; 17 /** 18 * Zookeeper 节点授权 19 * @author(alienware) 20 * @since 2015-6-14 21 */ 22 public class ZookeeperAuth implements Watcher { 23 24 /** 连接地址 */ 25 final static String CONNECT_ADDR = "192.168.80.88:2181"; 26 /** 测试路径 */ 27 final static String PATH = "/testAuth"; 28 final static String PATH_DEL = "/testAuth/delNode"; 29 /** 认证类型 */ 30 final static String authentication_type = "digest"; 31 /** 认证正确方法 */ 32 final static String correctAuthentication = "123456"; 33 /** 认证错误方法 */ 34 final static String badAuthentication = "654321"; 35 36 static ZooKeeper zk = null; 37 /** 计时器 */ 38 AtomicInteger seq = new AtomicInteger(); 39 /** 标识 */ 40 private static final String LOG_PREFIX_OF_MAIN = "【Main】"; 41 42 private CountDownLatch connectedSemaphore = new CountDownLatch(1); 43 44 @Override 45 public void process(WatchedEvent event) { 46 try { 47 Thread.sleep(200); 48 } catch (InterruptedException e) { 49 e.printStackTrace(); 50 } 51 if (event==null) { 52 return; 53 } 54 // 连接状态 55 KeeperState keeperState = event.getState(); 56 // 事件类型 57 EventType eventType = event.getType(); 58 // 受影响的path 59 String path = event.getPath(); 60 61 String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】"; 62 63 System.out.println(logPrefix + "收到Watcher通知"); 64 System.out.println(logPrefix + "连接状态:\t" + keeperState.toString()); 65 System.out.println(logPrefix + "事件类型:\t" + eventType.toString()); 66 if (KeeperState.SyncConnected == keeperState) { 67 // 成功连接上ZK服务器 68 if (EventType.None == eventType) { 69 System.out.println(logPrefix + "成功连接上ZK服务器"); 70 connectedSemaphore.countDown(); 71 } 72 } else if (KeeperState.Disconnected == keeperState) { 73 System.out.println(logPrefix + "与ZK服务器断开连接"); 74 } else if (KeeperState.AuthFailed == keeperState) { 75 System.out.println(logPrefix + "权限检查失败"); 76 } else if (KeeperState.Expired == keeperState) { 77 System.out.println(logPrefix + "会话失效"); 78 } 79 System.out.println("--------------------------------------------"); 80 } 81 /** 82 * 创建ZK连接 83 * 84 * @param connectString 85 * ZK服务器地址列表 86 * @param sessionTimeout 87 * Session超时时间 88 */ 89 public void createConnection(String connectString, int sessionTimeout) { 90 this.releaseConnection(); 91 try { 92 zk = new ZooKeeper(connectString, sessionTimeout, this); 93 //添加节点授权 94 zk.addAuthInfo(authentication_type,correctAuthentication.getBytes()); 95 System.out.println(LOG_PREFIX_OF_MAIN + "开始连接ZK服务器"); 96 //倒数等待 97 connectedSemaphore.await(); 98 } catch (Exception e) { 99 e.printStackTrace(); 100 } 101 } 102 103 /** 104 * 关闭ZK连接 105 */ 106 public void releaseConnection() { 107 if (this.zk!=null) { 108 try { 109 this.zk.close(); 110 } catch (InterruptedException e) { 111 } 112 } 113 } 114 115 /** 116 * 117 * <B>方法名称:</B>测试函数<BR> 118 * <B>概要说明:</B>测试认证<BR> 119 * @param args 120 * @throws Exception 121 */ 122 public static void main(String[] args) throws Exception { 123 124 ZookeeperAuth testAuth = new ZookeeperAuth(); 125 testAuth.createConnection(CONNECT_ADDR,2000); 126 List<ACL> acls = new ArrayList<ACL>(1); 127 for (ACL ids_acl : Ids.CREATOR_ALL_ACL) { 128 acls.add(ids_acl); 129 } 130 131 try { 132 zk.create(PATH, "init content".getBytes(), acls, CreateMode.PERSISTENT); 133 System.out.println("使用授权key:" + correctAuthentication + "创建节点:"+ PATH + ", 初始内容是: init content"); 134 } catch (Exception e) { 135 e.printStackTrace(); 136 } 137 try { 138 zk.create(PATH_DEL, "will be deleted! ".getBytes(), acls, CreateMode.PERSISTENT); 139 System.out.println("使用授权key:" + correctAuthentication + "创建节点:"+ PATH_DEL + ", 初始内容是: init content"); 140 } catch (Exception e) { 141 e.printStackTrace(); 142 } 143 144 // 获取数据 145 getDataByNoAuthentication(); 146 getDataByBadAuthentication(); 147 getDataByCorrectAuthentication(); 148 149 // 更新数据 150 updateDataByNoAuthentication(); 151 updateDataByBadAuthentication(); 152 updateDataByCorrectAuthentication(); 153 154 // 删除数据 155 deleteNodeByBadAuthentication(); 156 deleteNodeByNoAuthentication(); 157 deleteNodeByCorrectAuthentication(); 158 // 159 Thread.sleep(1000); 160 161 deleteParent(); 162 //释放连接 163 testAuth.releaseConnection(); 164 } 165 /** 获取数据:采用错误的密码 */ 166 static void getDataByBadAuthentication() { 167 String prefix = "[使用错误的授权信息]"; 168 try { 169 ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null); 170 //授权 171 badzk.addAuthInfo(authentication_type,badAuthentication.getBytes()); 172 Thread.sleep(2000); 173 System.out.println(prefix + "获取数据:" + PATH); 174 System.out.println(prefix + "成功获取数据:" + badzk.getData(PATH, false, null)); 175 } catch (Exception e) { 176 System.err.println(prefix + "获取数据失败,原因:" + e.getMessage()); 177 } 178 } 179 180 /** 获取数据:不采用密码 */ 181 static void getDataByNoAuthentication() { 182 String prefix = "[不使用任何授权信息]"; 183 try { 184 System.out.println(prefix + "获取数据:" + PATH); 185 ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null); 186 Thread.sleep(2000); 187 System.out.println(prefix + "成功获取数据:" + nozk.getData(PATH, false, null)); 188 } catch (Exception e) { 189 System.err.println(prefix + "获取数据失败,原因:" + e.getMessage()); 190 } 191 } 192 193 /** 采用正确的密码 */ 194 static void getDataByCorrectAuthentication() { 195 String prefix = "[使用正确的授权信息]"; 196 try { 197 System.out.println(prefix + "获取数据:" + PATH); 198 199 System.out.println(prefix + "成功获取数据:" + zk.getData(PATH, false, null)); 200 } catch (Exception e) { 201 System.out.println(prefix + "获取数据失败,原因:" + e.getMessage()); 202 } 203 } 204 205 /** 206 * 更新数据:不采用密码 207 */ 208 static void updateDataByNoAuthentication() { 209 210 String prefix = "[不使用任何授权信息]"; 211 212 System.out.println(prefix + "更新数据: " + PATH); 213 try { 214 ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null); 215 Thread.sleep(2000); 216 Stat stat = nozk.exists(PATH, false); 217 if (stat!=null) { 218 nozk.setData(PATH, prefix.getBytes(), -1); 219 System.out.println(prefix + "更新成功"); 220 } 221 } catch (Exception e) { 222 System.err.println(prefix + "更新失败,原因是:" + e.getMessage()); 223 } 224 } 225 226 /** 227 * 更新数据:采用错误的密码 228 */ 229 static void updateDataByBadAuthentication() { 230 231 String prefix = "[使用错误的授权信息]"; 232 233 System.out.println(prefix + "更新数据:" + PATH); 234 try { 235 ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null); 236 //授权 237 badzk.addAuthInfo(authentication_type,badAuthentication.getBytes()); 238 Thread.sleep(2000); 239 Stat stat = badzk.exists(PATH, false); 240 if (stat!=null) { 241 badzk.setData(PATH, prefix.getBytes(), -1); 242 System.out.println(prefix + "更新成功"); 243 } 244 } catch (Exception e) { 245 System.err.println(prefix + "更新失败,原因是:" + e.getMessage()); 246 } 247 } 248 249 /** 250 * 更新数据:采用正确的密码 251 */ 252 static void updateDataByCorrectAuthentication() { 253 254 String prefix = "[使用正确的授权信息]"; 255 256 System.out.println(prefix + "更新数据:" + PATH); 257 try { 258 Stat stat = zk.exists(PATH, false); 259 if (stat!=null) { 260 zk.setData(PATH, prefix.getBytes(), -1); 261 System.out.println(prefix + "更新成功"); 262 } 263 } catch (Exception e) { 264 System.err.println(prefix + "更新失败,原因是:" + e.getMessage()); 265 } 266 } 267 268 /** 269 * 不使用密码 删除节点 270 */ 271 static void deleteNodeByNoAuthentication() throws Exception { 272 273 String prefix = "[不使用任何授权信息]"; 274 275 try { 276 System.out.println(prefix + "删除节点:" + PATH_DEL); 277 ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null); 278 Thread.sleep(2000); 279 Stat stat = nozk.exists(PATH_DEL, false); 280 if (stat!=null) { 281 nozk.delete(PATH_DEL,-1); 282 System.out.println(prefix + "删除成功"); 283 } 284 } catch (Exception e) { 285 System.err.println(prefix + "删除失败,原因是:" + e.getMessage()); 286 } 287 } 288 289 /** 290 * 采用错误的密码删除节点 291 */ 292 static void deleteNodeByBadAuthentication() throws Exception { 293 294 String prefix = "[使用错误的授权信息]"; 295 296 try { 297 System.out.println(prefix + "删除节点:" + PATH_DEL); 298 ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null); 299 //授权 300 badzk.addAuthInfo(authentication_type,badAuthentication.getBytes()); 301 Thread.sleep(2000); 302 Stat stat = badzk.exists(PATH_DEL, false); 303 if (stat!=null) { 304 badzk.delete(PATH_DEL, -1); 305 System.out.println(prefix + "删除成功"); 306 } 307 } catch (Exception e) { 308 System.err.println(prefix + "删除失败,原因是:" + e.getMessage()); 309 } 310 } 311 312 /** 313 * 使用正确的密码删除节点 314 */ 315 static void deleteNodeByCorrectAuthentication() throws Exception { 316 317 String prefix = "[使用正确的授权信息]"; 318 319 try { 320 System.out.println(prefix + "删除节点:" + PATH_DEL); 321 Stat stat = zk.exists(PATH_DEL, false); 322 if (stat!=null) { 323 zk.delete(PATH_DEL, -1); 324 System.out.println(prefix + "删除成功"); 325 } 326 } catch (Exception e) { 327 System.out.println(prefix + "删除失败,原因是:" + e.getMessage()); 328 } 329 } 330 331 /** 332 * 使用正确的密码删除节点 333 */ 334 static void deleteParent() throws Exception { 335 try { 336 Stat stat = zk.exists(PATH_DEL, false); 337 if (stat == null) { 338 zk.delete(PATH, -1); 339 } 340 } catch (Exception e) { 341 e.printStackTrace(); 342 } 343 } 344 345 }
以上是关于WatcherZK状态事件类型 ,权限的主要内容,如果未能解决你的问题,请参考以下文章
React Hooks TypeScript 事件和状态类型
Android 逆向Linux 文件权限 ( Linux 权限简介 | 系统权限 | 用户权限 | 匿名用户权限 | 读 | 写 | 执行 | 更改组 | 更改用户 | 粘滞 )(代码片段
Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段