Curator 是 Apache ZooKeeper 的Java客户端库。
Zookeeper现有常见的Java API如:原生JavaAPI、Curator、ZkClient等。
pom.xml
4.0.0
com.example
demo
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.5.9
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
1.18.22
org.apache.zookeeper
zookeeper
3.9.0
org.apache.curator
curator-framework
5.2.1
org.apache.curator
curator-recipes
5.2.1
org.springframework.boot
spring-boot-maven-plugin
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
false
spring-milestones
Spring Milestones
https://repo.spring.io/milestone
false
spring-snapshots
Spring Snapshots
https://repo.spring.io/snapshot
false
application.properties
server.port= 8085
zookeeper.host= localhost:2181
一、建立连接
四个关键参数:
1、connectString 连接字符串 zkServer 地址和端口:"192.168.253.128:2181"
2、sessionTimeoutMs 会话超时时间,单位ms
3、connectionTimeoutMs 连接超时时间,单位ms
4、retryPolicy 重试策略
ZookeeperConfig
package com.example.demo.zk.config;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author yanqiuxiang
* @version 1.0
*/
@Configuration
public class ZookeeperConfig {
@Value("${zookeeper.host}")
private String host;
@Bean
public CuratorFramework curatorFramework() {
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
.connectString(host)
.sessionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(500, 5))
.build();
curatorFramework.start();
return curatorFramework;
}
}
ZookeeperController
二、创建节点:create 持久 临时 顺序 数据
1. 基本创建 :create().forPath("")
2. 创建节点 带有数据:create().forPath("",data)
3. 设置节点的类型:create().withMode().forPath("",data)
4. 创建多级节点 /app1/p1 :create().creatingParentsIfNeeded().forPath("",data)
package com.example.demo.zk.controller;
import com.example.demo.zk.JsonResult;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author yanqiuxiang
* @version 1.0
*/
@RestController
@RequestMapping(path = "/zookeeper", produces = "application/json;charset=utf-8")
public class ZookeeperController {
private final CuratorFramework curatorFramework;
@Autowired
public ZookeeperController(CuratorFramework curatorFramework) {
this.curatorFramework = curatorFramework;
}
/**
* 判断znode是否存在
* @param node 节点名称
*/
@RequestMapping(value = "/exist", method = RequestMethod.GET)
public JsonResult exist(String node) throws Exception {
Stat stat = curatorFramework.checkExists().forPath(node);
return new JsonResult(200, stat);
}
/**
* 创建一个znode
* @param node 节点名称
*/
@RequestMapping(value = "/create", method = RequestMethod.GET)
public JsonResult create(String node) throws Exception {
curatorFramework.create()
.creatingParentContainersIfNeeded()
/*
创建模式:常用的有
PERSISTENT:持久化节点,客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除,该节点就会永远存在。
PERSISTENT_SEQUENTIAL:持久化顺序编号目录节点,客户端与zookeeper断开连接后,该节点依旧存在,只是zookeeper给该节点名称进行顺序编号。
EPHEMERAL:临时目录节点,客户端与zookeeper断开连接后,该节点被删除。
EPHEMERAL_SEQUENTIAL:临时顺序编号目录节点,客户端与zookeeper断开连接后,该节点被删除,只是zookeeper给该节点名称进行顺序编号。
*/
.withMode(CreateMode.EPHEMERAL)
.forPath(node);
return new JsonResult("创建成功");
}
/**
* 设置znode节点的数据
* @param node 节点名称
* @param data 节点的数据
*/
@RequestMapping(value = "/setData", method = RequestMethod.GET)
public JsonResult setData(String node, String data) throws Exception {
curatorFramework.setData().forPath(node, data.getBytes(StandardCharsets.UTF_8));
return new JsonResult("设置成功");
}
/**
* 删除节点
* @param node 节点名称
*/
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public JsonResult delete(String node) throws Exception {
curatorFramework.delete().forPath(node);
return new JsonResult("删除成功");
}
/**
* 删除节点及其子节点的数据
* @param node 节点名称
*/
@RequestMapping(value = "/deleteDeeply", method = RequestMethod.GET)
public JsonResult deleteDeeply(String node) throws Exception {
curatorFramework.delete().deletingChildrenIfNeeded().forPath(node);
return new JsonResult("删除成功");
}
/**
* 获取节点的数据
* @param node 节点名称
*/
@RequestMapping(value = "/getData", method = RequestMethod.GET)
public JsonResult getData(String node) throws Exception {
byte[] bytes = curatorFramework.getData().forPath(node);
return new JsonResult(200, new String(bytes));
}
/**
* 获取当前节点的子节点数据
* @param node 节点名称
*/
@RequestMapping(value = "/getChildren", method = RequestMethod.GET)
public JsonResult> getChildren(String node) throws Exception {
List list = curatorFramework.getChildren().forPath(node);
return new JsonResult(200, list);
}
}
JsonResult
package com.example.demo.zk;
import java.io.Serializable;
/**
* 用于封装服务器到客户端的Json返回值
* @author yanqiuxiang
*
*/
public class JsonResult implements Serializable {
//Serializable将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本
public static final int SUCCESS=0;
public static final int ERROR=1;
public static final int OTHER=2;
private int state;
private String message = "";
private T data;
private String pass="";
public JsonResult(){
state = SUCCESS;
}
//为了方便,重载n个构造器
public JsonResult(int state, String message, T data) {
super();
this.state = state;
this.message = message;
this.data = data;
}
public JsonResult(int state,String error){
this(state,error,null);
}
public JsonResult(int state,T data){
this(state,"",data);
}
public JsonResult(String error){
this(ERROR,error,null);
}
public JsonResult(T data){
this(SUCCESS,"",data);
}
public JsonResult(int state){
this(state,"",null);
}
public JsonResult(Throwable e){
this(ERROR,e.getMessage(),null);
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static int getSuccess() {
return SUCCESS;
}
public static int getError() {
return ERROR;
}
@Override
public String toString() {
return "JsonResult [state=" + state + ", message=" + message + ", pass=" + pass + ", data=" + data + "]";
}
}