启动zk报错:
g.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'zkUtil': Unsatisfied dependency expressed through field 'zkClient'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'zookeeperConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'zookeeper.address' in value "${zookeeper.address}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:639) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:397) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1429) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
起始报错中写的很清楚,
Could not resolve placeholder 'zookeeper.address' in value "${zookeeper.address}"
发现在properties和自己的zookeeperConfig文件中对不上,,如果你是抄的话
解决方案如下
在你的zookeeperConfig中修改为
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.CountDownLatch;
@Configuration
public class zookeeperConfig {
private static final Logger logger = LoggerFactory.getLogger(zookeeperConfig.class);
@Value("${spring.cloud.zookeeper.address}")
private String connectString;
@Value("${spring.cloud.zookeeper.timeout}")
private int sessionTimeout;
public String getConnectString() {
return connectString;
}
public void setConnectString(String connectString) {
this.connectString = connectString;
}
public int getSessionTimeout() {
return sessionTimeout;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Bean(name = "zkClient")
public ZooKeeper zkClient() {
ZooKeeper zooKeeper = null;
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 如果收到了服务端的响应事件,说明连接成功
if (Event.KeeperState.SyncConnected == event.getState()) {
countDownLatch.countDown();
}
}
});
countDownLatch.await();
logger.info(" 初始化ZooKeeper连接状态: {}",zooKeeper.getState());
} catch (Exception e) {
logger.error(" 初始化Zookeeper连接状态异常: {}",e.getMessage());
}
return zooKeeper;
}
}
而不是
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.CountDownLatch;
@Configuration
public class zookeeperConfig {
private static final Logger logger = LoggerFactory.getLogger(zookeeperConfig.class);
@Value("${zookeeper.address}")
private String connectString;
@Value("$spring.cloud.zookeeper.timeout}")
private int sessionTimeout;
public String getConnectString() {
return connectString;
}
public void setConnectString(String connectString) {
this.connectString = connectString;
}
public int getSessionTimeout() {
return sessionTimeout;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Bean(name = "zkClient")
public ZooKeeper zkClient() {
ZooKeeper zooKeeper = null;
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 如果收到了服务端的响应事件,说明连接成功
if (Event.KeeperState.SyncConnected == event.getState()) {
countDownLatch.countDown();
}
}
});
countDownLatch.await();
logger.info(" 初始化ZooKeeper连接状态: {}",zooKeeper.getState());
} catch (Exception e) {
logger.error(" 初始化Zookeeper连接状态异常: {}",e.getMessage());
}
return zooKeeper;
}
}
或者
在application.properties中修改为
zookeeper.address=192.168.5.5:2181
zookeeper.timeout=4000
而不是:
spring.cloud.zookeeper.address=192.168.5.5:2181
spring.cloud.zookeeper.timeout=4000
这个问题主要出现在对properties中key values的用法,但是在一定程度上是目前很多blog在抄的结果,这个避雷!!!!
贴上个人的
zookeeper配置,在spring boot时配置项及zookeeper及zookeeper单机版的安装
对于zookeeper的安装选择 要选择bin.tar,
解压,配置一下 conf中的zoo.cfg(zoo_sample.cfg
复制改名)文件然后启动bin中的zkServer.sh文件即可
我的zoo.cfg配置如下:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/data/zk/data
dataLogDir=/data/zk/log
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true
在springboot的配置如下
zookeeperConfig文件:
package com.sims.zookeeper;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.CountDownLatch;
@Configuration
public class zookeeperConfig {
private static final Logger logger = LoggerFactory.getLogger(zookeeperConfig.class);
@Value("${spring.cloud.zookeeper.address}")
private String connectString;
@Value("${spring.cloud.zookeeper.timeout}")
private int sessionTimeout;
public String getConnectString() {
return connectString;
}
public void setConnectString(String connectString) {
this.connectString = connectString;
}
public int getSessionTimeout() {
return sessionTimeout;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
@Bean(name = "zkClient")
public ZooKeeper zkClient() {
ZooKeeper zooKeeper = null;
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 如果收到了服务端的响应事件,说明连接成功
if (Event.KeeperState.SyncConnected == event.getState()) {
countDownLatch.countDown();
}
}
});
countDownLatch.await();
logger.info(" 初始化ZooKeeper连接状态: {}",zooKeeper.getState());
} catch (Exception e) {
logger.error(" 初始化Zookeeper连接状态异常: {}",e.getMessage());
}
return zooKeeper;
}
}
ZKUtil文件如下:
package com.sims.zookeeper;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ZkUtil {
private static final Logger logger = LoggerFactory.getLogger(ZkUtil.class);
@Autowired
private ZooKeeper zkClient;
@Autowired
private zookeeperConfig ZooKeeper;
/**
* 创建持久化节点
* -- 客户端断开连接后,节点数据持久化在磁盘上,不会被删除。
*
* @param path 路径
* @param data 数据
*/
public boolean createPerNode(String path, String data) {
try {
// 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
zkClient.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
return true;
} catch (Exception e) {
logger.error("创建持久化节点异常,路径: {}, 数据: {}, 异常: {}", path, data, e);
return false;
}
}
/**
* 创建临时节点
* -- 客户端断开连接后,节点将被删除。
*
* @param path 路径
* @param data 数据
*/
public boolean createTmpNode(String path, String data) {
try {
// 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
zkClient.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
return true;
} catch (Exception e) {
logger.error("创建临时节点异常,路径: {}, 数据: {}, 异常: {}", path, data, e);
return false;
}
}
/**
* 创建自定义节点
*
* @param path 路径
* @param data 数据
* @param acl 节点权限
* @param createMode 节点类型
*/
public boolean createNode(String path, String data, List<ACL> acl, CreateMode createMode) {
try {
// 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
zkClient.create(path, data.getBytes(), acl, createMode);
return true;
} catch (Exception e) {
logger.error("创建节点异常,路径: {}, 数据: {}, 异常: {}", path, data, e);
return false;
}
}
/**
* 修改节点
*
* @param path 路径
* @param data 数据
*/
public boolean updateNode(String path, String data) {
try {
// zk的数据版本是从0开始计数的。如果客户端传入的是-1,则表示zk服务器需要基于最新的数据进行更新。如果对zk的数据节点的更新操作没有原子性要求则可以使用-1.
// version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
zkClient.setData(path, data.getBytes(), -1);
return true;
} catch (Exception e) {
logger.error("修改节点异常,路径: {}, 数据: {}, 异常: {}", path, data, e);
return false;
}
}
/**
* 删除节点
*
* @param path 路径
*/
public boolean deleteNode(String path) {
try {
// version参数指定要更新的数据的版本, 如果version和真实的版本不同, 更新操作将失败. 指定version为-1则忽略版本检查
zkClient.delete(path, -1);
return true;
} catch (Exception e) {
logger.error("删除节点异常,路径: {}, 异常: {}", path, e);
return false;
}
}
/**
* 判断指定节点是否存在
*
* @param path 路径
* @param needWatch 指定是否复用zookeeper中默认的Watcher
* @return 结果
*/
public Stat exists(String path, boolean needWatch) {
try {
return zkClient.exists(path, needWatch);
} catch (Exception e) {
logger.error("判断指定节点是否存在异常,路径: {}, 异常: {}", path, e);
return null;
}
}
/**
* 检测结点是否存在 并设置监听事件
* 三种监听类型: 创建,删除,更新
*
* @param path 路径
* @param watcher 传入指定的监听类
*/
public Stat exists(String path, Watcher watcher) {
try {
return zkClient.exists(path, watcher);
} catch (Exception e) {
logger.error("判断指定节点是否存在异常,路径: {}, 异常: {}", path, e);
return null;
}
}
/**
* 获取当前节点的子节点(不包含孙子节点)
*
* @param path 父节点path
*/
public List<String> getChildren(String path) throws KeeperException, InterruptedException {
List<String> list = zkClient.getChildren(path, false);
return list;
}
/**
* 获取指定节点的值
*
* @param path 路径
*/
public String getData(String path, Watcher watcher) {
try {
Stat stat = new Stat();
byte[] bytes = zkClient.getData(path, watcher, stat);
return new String(bytes);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// /**
// * 注册监听
// * @param watcher 监听类
// */
// public void registerWatch(Watcher watcher) throws IOException {
// ZooKeeper zooKeeper = new ZooKeeper(ZooKeeper.getConnectString(), ZooKeeper.getSessionTimeout(), watcher);
// }
}
CustomWatcher文件:
package com.sims.zookeeper;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CustomWatcher implements Watcher {
private static final Logger logger = LoggerFactory.getLogger(CustomWatcher.class);
@Override
public void process(WatchedEvent event) {
logger.info("监听事件的状态: {}",event.getState());
logger.info("监听事件的路径: {}",event.getPath());
logger.info("监听事件的类型: {}",event.getType());
}
}
依赖:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.7.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
绝大多数代码在csdn及简书中大佬所提供,但是不正确,建议后来者着重,这些问题,假如想发,请 务必校验!如果错,请评论,我将更正!