java springboot整合zookeeper增删改查入门教程

zookeeper的安装与集群搭建参考:https://www.cnblogs.com/zwcry/p/10272506.html

描述:本章主要讲java代码如何实现zookeeper节点的增删改查,用法与解释全部在注释里。

   本教程的工程,使用maven、jdk8、springboot、zookeeper 3.4.12

   重点:大家学会增删改查后,不妨动脑想下,zookeeper如何实现分布式锁,小小的提示下,竞争创建临时节点,创建成功者,则获得锁。

   注:请注意log4j2的配置,因为是java测试,并没有通过web、servlet启动程序,所以请把log4j2放在资源目录的根目录,我是新建了一个资源目录包log4j,将log4j2.xml放在该目录下。

1、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.1.RELEASE</version></parent><groupId>com.qy.code</groupId><artifactId>qy-zk</artifactId><version>0.0.1-SNAPSHOT</version><packaging>pom</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion><maven.test.skip>true</maven.test.skip><java.version>1.8</java.version><spring.boot.version>2.0.1.RELEASE</spring.boot.version><qy.code.version>0.0.1-SNAPSHOT</qy.code.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><!-- 不使用springboot默认log --><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper --><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.12</version><!-- 排除冲突jar --><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions></dependency></dependencies><repositories><repository><id>nexus-aliyun</id><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots></repository></repositories><pluginRepositories><pluginRepository><id>nexus-aliyun</id><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots></pluginRepository></pluginRepositories><build><plugins><!-- 要将源码放上去,需要加入这个插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><configuration><attach>true</attach></configuration><executions><execution><phase>compile</phase><goals><goal>jar</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build>
</project>

2.log4j2.xml

注:请注意log4j2的配置,因为是java测试,并没有通过web、servlet启动程序,所以请把log4j2放在资源目录的根目录,我是新建了一个资源目录包log4j,将log4j2.xml放在该目录下。

<?xml version="1.0" encoding="UTF-8"?>
<!-- log4j2 本身日志打印级别,以及重新刷新配置文件的时间-->
<Configuration status="WARN" monitorInterval="5"><Properties><Property name="log-path">logs</Property><Property name="log-file-temp">temp.log</Property><Property name="log-file-info">info.log</Property><Property name="log-file-warn">warn.log</Property><Property name="log-file-error">error.log</Property><!-- 输出格式 --><!-- <Property name="pattern">%p [%date{yyyy-MM-dd HH:mm:ss,SSS}] [%thread] %l %m %n </Property> --><Property name="pattern">%m %n </Property><!-- 日志切割的最小单位 --><property name="every_file_size">1M</property></Properties><Appenders><!-- 重置太打印 打印debug及以上级别 --><Console name="Console-Appender" target="SYSTEM_OUT"><ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" /><PatternLayout pattern="${pattern}"/></Console><!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用--><File name="RollingFile-Appender-Temp" fileName="${log-path}/${log-file-temp}" append="false"><PatternLayout pattern="${pattern}"/></File> <!-- 这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--><RollingFile name="RollingFile-Appender-INFO" fileName="${log-path}/${log-file-info}" append="true"filePattern="${log-path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log"><!-- 只输出INFO级别 --><Filters><ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY" /><ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL" /><ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL" /></Filters><PatternLayout pattern="${pattern}" /><SizeBasedTriggeringPolicy size="${every_file_size}"/><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了10 --><DefaultRolloverStrategy max="10"/></RollingFile><RollingFile name="RollingFile-Appender-WARN" fileName="${log-path}/${log-file-warn}" append="true"filePattern="${log-path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log"><!-- 只输出Warn级别 --><Filters><ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY" /><ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL" /></Filters><PatternLayout pattern="${pattern}" /><SizeBasedTriggeringPolicy size="${every_file_size}"/><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了10 --><DefaultRolloverStrategy max="10"/></RollingFile><RollingFile name="RollingFile-Appender-ERROR" fileName="${log-path}/${log-file-error}" append="true"filePattern="${log-path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log"><!-- 只输出ERROR级别 --><Filters><ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY" /></Filters><PatternLayout pattern="${pattern}" /><SizeBasedTriggeringPolicy size="${every_file_size}"/><!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了10 --><DefaultRolloverStrategy max="10"/></RollingFile></Appenders><Loggers><logger name="java.sql" level="debug" additivity="false"><appender-ref ref="Console-Appender"/></logger><logger name="com.ibatis" level="debug" additivity="false"><appender-ref ref="Console-Appender"/></logger><!-- 第三方的软件日志级别 --><logger name="org.springframework" level="info" additivity="true"><AppenderRef ref="RollingFile-Appender-WARN" /><AppenderRef ref="RollingFile-Appender-ERROR" /></logger><!-- 第三方的软件日志级别 --><logger name="org.apache" level="warn" additivity="true"><AppenderRef ref="RollingFile-Appender-WARN" /><AppenderRef ref="RollingFile-Appender-ERROR" /></logger><!-- 异步输出 --><Root level="INFO"><AppenderRef ref="Console-Appender"/><AppenderRef ref="RollingFile-Appender-Temp"/><AppenderRef ref="RollingFile-Appender-INFO" /><AppenderRef ref="RollingFile-Appender-WARN" /><AppenderRef ref="RollingFile-Appender-ERROR" /></Root></Loggers>
</Configuration>

3.增删改查.java

package com.qy.zk;import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;/*** 描述:zookeeper增删改查* 作者:七脉* 重点:删除、修改、查询所用的version版本号,分布式事务锁的实现方式,乐观锁。ACL权限:所有人、限定人、限定IP等*/
public class MyZkConnect{private static  Logger log=LogManager.getLogger(MyZkConnect.class);//集群节点public static final String zkServerClusterConnect = "192.168.159.129:2181,192.168.159.129:2182,192.168.159.129:2183";//单一节点public static final String zkServerSingleConnect = "192.168.159.129:2181";//超时毫秒数public static final int timeout = 3000;public static void main(String[] args) throws InterruptedException, IOException, KeeperException {//建立连接ZooKeeper zk = connect();//zk.close();//关闭后不支持重连log.info("zk 状态:"+zk.getState());/**恢复会话连接**///long sessionId = zk.getSessionId();//byte[] sessionPasswd = zk.getSessionPasswd();//zk2会话重连后,zk会话将失效,不再支持做增删改查操作。//ZooKeeper zk2 = reconnect(sessionId, sessionPasswd);/**创建节点**///create(zk, "/myzk", "myzk");/**查询节点Data**/queryData(zk, "/myzk");/**修改节点data**///update(zk, "/myzk", "myzk-update");/**删除节点**///delete(zk, "/myzk");
    }/*** 描述:建立连接* 作者:七脉* @return* @throws IOException* @throws InterruptedException*/public static ZooKeeper connect() throws IOException, InterruptedException{CountDownLatch cdl = new CountDownLatch(1);log.info("准备建立zk服务");ZooKeeper zk = new ZooKeeper(zkServerClusterConnect, timeout, new MyZkWatcher(cdl,"建立连接"));log.info("完成建立zk服务");cdl.await();//这里为了等待wather监听事件结束return zk;}/*** 描述:重新连接服务* 作者:七脉* @param sessionId 现有会话ID* @param sessionPasswd 现有会话密码* @return* @throws IOException* @throws InterruptedException* 重点:关闭后的会话连接,不支持重连。重连后,前会话连接将会失效。*/public static ZooKeeper reconnect(long sessionId, byte[] sessionPasswd) throws IOException, InterruptedException{CountDownLatch cdl = new CountDownLatch(1);log.info("准备重新连接zk服务");ZooKeeper zk = new ZooKeeper(zkServerClusterConnect, timeout, new MyZkWatcher(cdl,"重新连接"), sessionId, sessionPasswd);log.info("完成重新连接zk服务");cdl.await();//这里为了等待wather监听事件结束return zk;}/*** 描述:创建节点* 作者:七脉* @param zk* @param nodePath* @param nodeData* @throws KeeperException* @throws InterruptedException*/public static void create(ZooKeeper zk,String nodePath,String nodeData) throws KeeperException, InterruptedException{log.info("开始创建节点:{}, 数据:{}",nodePath,nodeData);List<ACL> acl = Ids.OPEN_ACL_UNSAFE;CreateMode createMode = CreateMode.PERSISTENT;String result = zk.create(nodePath, nodeData.getBytes(), acl, createMode);//创建节点有两种,上面是第一种,还有一种可以使用回调函数及参数传递,与上面方法名称相同。log.info("创建节点返回结果:{}",result);log.info("完成创建节点:{}, 数据:{}",nodePath,nodeData);}/*** 描述:查询节点结构信息* 作者:七脉* @param zk* @param nodePath* @return* @throws KeeperException* @throws InterruptedException*/public static Stat queryStat(ZooKeeper zk,String nodePath) throws KeeperException, InterruptedException{log.info("准备查询节点Stat,path:{}", nodePath);Stat stat = zk.exists(nodePath, false);log.info("结束查询节点Stat,path:{},version:{}", nodePath, stat.getVersion());return stat;}/*** 描述:查询节点Data值信息* 作者:七脉* @param zk* @param nodePath* @return* @throws KeeperException* @throws InterruptedException*/public static String queryData(ZooKeeper zk,String nodePath) throws KeeperException, InterruptedException{log.info("准备查询节点Data,path:{}", nodePath);String data = new String(zk.getData(nodePath, false, queryStat(zk, nodePath)));log.info("结束查询节点Data,path:{},Data:{}", nodePath, data);return data;}/*** 描述:修改节点* 作者:七脉* @param zk* @param nodePath* @param nodeData* @throws KeeperException* @throws InterruptedException* 重点:每次修改节点的version版本号都会变更,所以每次修改都需要传递节点原版本号,以确保数据的安全性。*/public static Stat update(ZooKeeper zk,String nodePath,String nodeData) throws KeeperException, InterruptedException{//修改节点前先查询该节点信息Stat stat = queryStat(zk, nodePath);log.info("准备修改节点,path:{},data:{},原version:{}", nodePath, nodeData, stat.getVersion());Stat newStat = zk.setData(nodePath, nodeData.getBytes(), stat.getVersion());//修改节点值有两种方法,上面是第一种,还有一种可以使用回调函数及参数传递,与上面方法名称相同。//zk.setData(path, data, version, cb, ctx);log.info("完成修改节点,path:{},data:{},现version:{}", nodePath, nodeData, newStat.getVersion());return stat;}/*** 描述:删除节点* 作者:七脉* @param zk* @param nodePath* @throws InterruptedException* @throws KeeperException*/public static void delete(ZooKeeper zk,String nodePath) throws InterruptedException, KeeperException{//删除节点前先查询该节点信息Stat stat = queryStat(zk, nodePath);log.info("准备删除节点,path:{},原version:{}", nodePath, stat.getVersion());zk.delete(nodePath, stat.getVersion());//修改节点值有两种方法,上面是第一种,还有一种可以使用回调函数及参数传递,与上面方法名称相同。//zk.delete(path, version, cb, ctx);log.info("完成删除节点,path:{}", nodePath);}
}

4.watcher观察者.java

package com.qy.zk;import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 描述:ZK服务观察者事件* 作者:七脉*/
public class MyZkWatcher implements Watcher{private static final Logger log = LoggerFactory.getLogger(MyZkWatcher.class);//异步锁private CountDownLatch cdl;//标记private String mark;public MyZkWatcher(CountDownLatch cdl,String mark) {this.cdl = cdl;this.mark = mark;}//监听事件处理方法public void process(WatchedEvent event) {log.info(mark+" watcher监听事件:{}",event);cdl.countDown();}}

本章节用到了CountDownLatch,不会的可以学下https://www.cnblogs.com/zwcry/p/9662499.html

源码:https://pan.baidu.com/s/1nWQvN9l2SsGupY6LPP0gTg

转载于:https://www.cnblogs.com/zwcry/p/10407806.html

java springboot整合zookeeper入门教程(增删改查)相关推荐

  1. java上安装zookeeper并且实现增删改查

    目录 一..创建Maven工具 二.将Maven的默认配置文件设置为自己下载的配置文件(非必要) 三.在maven文件中导入zookeeper依赖 四.创建增删改查类MyzkTest 五.实现zook ...

  2. springboot整合IDAP,实现增删改查

    看了网上很多资料,大多是用于查询认证.增删改很少,特在此整理一下.供大家学习. 注:前置条件,ad域证书已经导入到jdk(大家可以查看我另一篇关于ad证书导入到jdk中) 1.idea创建spring ...

  3. SpringBoot整合MyBatis实现数据增删改查

    项目结构 pom.xml <!--freemarker支持--><dependency><groupId>org.springframework.boot</ ...

  4. java jdbc 连接mysql数据库 实现增删改查

    好久没有写博文了,写个简单的东西热热身,分享给大家. jdbc相信大家都不陌生,只要是个搞java的,最初接触j2ee的时候都是要学习这么个东西的,谁叫程序得和数据库打交道呢!而jdbc就是和数据库打 ...

  5. java之全文索引搜索lucene之增删改查文档与中文分词搜索

    java之全文索引搜索lucene之增删改查文档与中文分词搜索 接上文,接下来介绍一个lucene的各种query,然后介绍一下中文全文索引搜索. 对于各种query,我就直接上代码了,具体的话,我已 ...

  6. SSH(Struts 2.3.31 + Spring 4.1.6 + Hibernate 5.0.12 + Ajax)框架整合实现简单的增删改查(包含分页,Ajax 无刷新验证该用户是否存在)...

    软件152 余建强 该文将以员工.部门两表带领大家进入SSH的整合教程: 源码下载:http://download.csdn.net/detail/qq_35318576/9877235 SSH 整合 ...

  7. 超全流程-idea对springboot+ssm的部署实现增删改查

    由于前段时间完成期末项目,在期末学科里也学到很多,但这里不书写接近2个月没有更新博客, 因为之前有过较为成熟的ssh框架运用以及理解的经验,我打算在寒假学习一下ssm,联合springboot, 学习 ...

  8. java对mysql的简单操作——增删改查的总结

    增删改查的详细内容可以点击以下链接: java对mysql的简单操作--增加数据 java对mysql的简单操作--删除数据 java对mysql的简单操作--修改数据 java连接mysql5.1教 ...

  9. springboot+springm vc+mybatis实现增删改查案例!

    大家好,我是雄雄,欢迎关注微信公众号[雄雄的小课堂]. 前言 最近这几天都在看关于springboot的内容,每天新会获得点新收获,并且都总结发在公众号中:最后经过不懈努力,不断查找相关网页,解决各种 ...

最新文章

  1. Android中应用百度地图API开发地图APP实例-显示百度地图
  2. 中文通用百科知识图谱(CN-DBpedia)
  3. 16-CoreData之多表关联(存储自定义数据模型)
  4. [ffmpeg] 解码API
  5. SAP Fiori Elements - Account F4 help - how value help dialog is populated
  6. 面试题——死锁的实现
  7. 学生信,不是贪多的,而是求精的!
  8. ZZULIOJ 1132: 数字字符统计
  9. python显示gif图片报错_用Python制作在地图上模拟瘟疫扩散的Gif图
  10. 只需一条信息即可远程利用严重的思科 Jabber RCE缺陷
  11. django multidb --- router
  12. css vue 内联_Vue绑定内联样式问题
  13. kindle可以上网但是无法下载_您的Kindle已连接WiFi网络,但无法连接互联网的解决办法...
  14. PPT制作教程—基础技巧
  15. 毕业论文选题之开题报告
  16. 基于CPU+GPU的H.264编码器并行编码设计
  17. 联想笔记本e43l_联想昭阳e43l
  18. 注解和反射复习——B站
  19. 使鼠标保持按住状态_让电脑也能听、会写、还会说!小米小爱鼠标抢先体验
  20. oracle rebuild online,rebuild online 请慎用

热门文章

  1. 2022-11-28关键词扩充,文章自动生成,采集php源码,自动配图源码,SEO提高收录权重无限长尾词
  2. 薪资9k!三年教培老师被优化,选择转行软件测试实现再就业
  3. 名人励志故事:比起点更重要的是梦想
  4. vue拖拽功能,提高你的开发效率
  5. 【Web实战-Tomcat-Servlet-Thymeleaf -JDBC-MySQL】浏览器页面显示数据库数据(水果库存系统)
  6. 金融数据分析必备的126个数据源
  7. 开车人千金难买的知识!(组图)
  8. Pgbouncer最佳实践:系列一
  9. linux c语言sleep的时间实验
  10. 两个国家级宝藏网站推荐