共享一份闲暇之余编写的Zookeeper客户端使用的一些最基础的代码,下面实现的是一个网络聊天的小程序
需要将Zookeeper的服务器启动好了之后,修改其中的IP地址就可,可配置多个服务器IP
package yz.web;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NodeExistsException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class AppClient implements Watcher, Runnable{
private String clientListNode = "/chat";
private ZooKeeper zk;
private Stat stat = new Stat();
private volatile List<String> onlineUsers = new ArrayList<String>();
private String myself = "";
private CountDownLatch connectedSignal = new CountDownLatch(1);
public void connectZookeeper() throws Exception {
zk = new ZooKeeper("192.168.20.97:2181,192.168.20.97:2182,192.168.20.97:2183,192.168.20.97:2184,192.168.20.97:2185", 5000, this);
connectedSignal.await(); // 等待连接完成
userLogin();
}
private void userLogin() throws IOException, KeeperException, InterruptedException {
showOnlineUsers();
myself = inputName();
createNamePath(myself);
zk.getData(clientListNode, true, stat); // 注册NodeDataChanged事件的watcher
}
private void showOnlineUsers() throws KeeperException, InterruptedException {
List<String> onlineUsers = zk.getChildren(clientListNode, true);
if (onlineUsers.size() > 0) {
System.out.println("The online users is shown as below:");
for (String username : onlineUsers) {
System.out.println(username);
this.onlineUsers.add(username);
}
} else {
System.out.println("No one is online!");
}
}
private void createNamePath(String name) throws KeeperException, InterruptedException, IOException {
try {
zk.create(clientListNode + "/" + name, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} catch (NodeExistsException e) {
System.out.println("The name is duplicated...");
userLogin();
} catch (Exception e) {
System.out.println("Occur unexpected exception...");
userLogin();
}
}
private String inputName() throws IOException {
System.out.println("Please input your name:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
return name;
}
private String getLastPathName(String path) {
return path.substring(path.lastIndexOf("/") + 1, path.length());
}
public void handleChat() throws InterruptedException {
run();
Thread.sleep(Long.MAX_VALUE);
}
public void run() {
while (true) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String chatContent = br.readLine();
if (chatContent == null || "".equals(chatContent)) {
continue;
}
zk.setData(clientListNode, (myself + " says: " + chatContent).getBytes("utf-8"), -1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void process(WatchedEvent event) {
String path = event.getPath();
if (event.getType() == Event.EventType.None) {
// We are are being told that the state of the
// connection has changed
switch (event.getState()) {
case SyncConnected:
// In this particular example we don't need to do anything
// here - watches are automatically re-registered with
// server and any watches triggered while the client was
// disconnected will be delivered (in order of course)
connectedSignal.countDown();// 倒数-1
break;
case Expired:
// It's all over
break;
default:
break;
}
} else {
if (event.getType() == EventType.NodeChildrenChanged && path.equals(clientListNode)) {
try {
checkUsers();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (event.getType() == EventType.NodeDataChanged) {
try {
String chatContent = new String(zk.getData(clientListNode, true, stat), "utf-8");
System.out.println(chatContent);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
protected void checkUsers() throws KeeperException, InterruptedException {
List<String> onlineUsers = zk.getChildren(clientListNode, true);
int preUserNum = this.onlineUsers.size();
int nowUserNum = onlineUsers.size();
List<String> tempList = new ArrayList<String>(Arrays.asList(new String[this.onlineUsers.size()]));
Collections.copy(tempList, this.onlineUsers);
if (preUserNum == nowUserNum) {
return;
} else if (preUserNum > nowUserNum) {
tempList.removeAll(onlineUsers);
someoneLogout(tempList);
} else if (preUserNum < nowUserNum) {
onlineUsers.removeAll(tempList);
someoneLogin(onlineUsers);
}
}
protected void someoneLogout(List<String> paths) {
for (String path : paths) {
String username = getLastPathName(path);
if (onlineUsers.contains(username)) {
System.out.println(username + " is logout...");
onlineUsers.remove(username);
}
}
}
private void someoneLogin(List<String> paths) {
for (String path : paths) {
String username = getLastPathName(path);
if (!onlineUsers.contains(username)) {
System.out.println(username + " is login...");
onlineUsers.add(username);
}
}
}
public static void main(String[] args) {
try {
AppClient ac = new AppClient();
ac.connectZookeeper();
ac.handleChat();
} catch(Exception e){
e.printStackTrace();
}
}
}
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>