Spring-利用InitializingBean接口和zookeeper实现项目初始化缓存以及同步监听

1.先贴出几个需要用到的工具类

ZkClientUtils
import com.ithzk.common.PropertiesUtil;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.log4j.Logger;
import org.apache.zookeeper.data.Stat; import java.util.List; /**
* zookeeper客户端工具类
* @author hzk
* @date 2018/3/15
*/
public class ZkClientUtils { private static final Logger logger = Logger.getLogger(ZkClientUtils.class); private CuratorFramework client; private String ZK_ADDRESS; public ZkClientUtils() {
ZK_ADDRESS = PropertiesUtil.getValueByBundle("config","zk.address");
this.client = CuratorFrameworkFactory.newClient(ZK_ADDRESS,new RetryNTimes(10, 5000));
this.client.start();
} public CuratorFramework getClient(){
return this.client;
} /**
* 创建节点
* @param zkPath 路径
* @param data 数据
* @return
*/
public boolean create(String zkPath,String data){
try {
// 如果父节点不存在,则在创建节点的同时创建父节点
client.create().creatingParentsIfNeeded().forPath(zkPath, data.getBytes("utf-8"));
return true;
} catch (Exception e) {
e.printStackTrace();
logger.error("----- create zk node error:"+e.getMessage());
}
return false;
} /**
* 获取节点值
* @param zkPath 路径
* @return
*/
public String getZnodeData(String zkPath){
try {
byte[] datas = client.getData().forPath(zkPath);
return new String(datas,"utf-8");
} catch (Exception e) {
e.printStackTrace();
logger.error("----- get zk node data error:"+e.getMessage());
}
return null;
} /**
* 设置节点值
* @param zkPath 路径
* @param data 数据
* @return
*/
public boolean set(String zkPath,String data){
try {
if(isExists(zkPath)){
client.setData().forPath(zkPath, data.getBytes("utf-8"));
}else {
create(zkPath, data);
}
return true;
} catch (Exception e) {
e.printStackTrace();
logger.error("----- set zk node data error:"+e.getMessage());
}
return false;
} /**
* 检验节点是否存在
* @param zkPath 路径
* @return
* @throws Exception
*/
public boolean isExists(String zkPath) throws Exception{
Stat stat = client.checkExists().forPath(zkPath);
return null != stat;
} /**
* 获取子节点列表
* @param zkPath 路径
* @return
*/
public List<String> list(String zkPath){
try {
return client.getChildren().forPath(zkPath);
} catch (Exception e) {
e.printStackTrace();
logger.error("----- get zk children node list error:"+e.getMessage());
}
return null;
}
public void close(){
client.close();
} }
WorkerPool
import java.util.concurrent.*;

public class WorkerPool {

    /**
* 线程池执行任务
* @param command
*/
public void exec(Runnable command){
ThreadFactory threadFactory = Executors.defaultThreadFactory();
ArrayBlockingQueue queue = new ArrayBlockingQueue<Runnable>(2);
ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, queue, threadFactory);
executorPool.execute(command);
}
}
IUpdateLocalCacheData
/**
* @author hzk
* @date 2018/3/15
*/
public interface IUpdateLocalCacheData { void change(Node node);
}
RetryRecord
/**
* 缓存重试统计类
* @author hzk
* @date 2018/3/16
*/
public class RetryRecord { private String lastRecordTime; private Integer retryCount; public RetryRecord(String lastRecordTime, Integer retryCount) {
this.lastRecordTime = lastRecordTime;
this.retryCount = retryCount;
} public String getLastRecordTime() {
return lastRecordTime;
} public void setLastRecordTime(String lastRecordTime) {
this.lastRecordTime = lastRecordTime;
} public Integer getRetryCount() {
return retryCount;
} public void setRetryCount(Integer retryCount) {
this.retryCount = retryCount;
}
}

实现InitializingBean接口的Bean

package com.ithzk.common.listener;

import com.ithzk.common.zk.CacheDataSynServerHandle;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.context.ServletContextAware; import javax.servlet.ServletContext; /**
* @author hzk
* @date 2018/3/15
*/
public class InitDataListener implements InitializingBean,ServletContextAware { private static final Logger logger = Logger.getLogger(InitDataListener.class); public static ServletContext servletContext; @Override
public void setServletContext(ServletContext arg0) {
InitDataListener.servletContext = arg0;
} @Override
public void afterPropertiesSet() throws Exception {
//初始化数据 加载数据到本地缓存
logger.info("----------------- init cache data.. -----------------------");
new CacheDataSynServerHandle().loadLocal(); //注册zk监听节点变化 同步数据
new CacheDataSynServerHandle().start();
logger.info("----------------- init cache data complete -----------------------");
}
}

CacheDataSynServerHandle

import com.ithzk.common.BeanFactoryUtil;
import com.ithzk.common.Constants;
import com.ithzk.common.JsonUtil;
import com.ithzk.common.PropertiesUtil;
import com.ithzk.common.dic.LoadData;
import com.ithzk.common.zk.ifc.IUpdateLocalCacheData;
import com.ithzk.dto.out.BaseResponse;
import com.ithzk.dto.out.DictionaryResponse;
import com.ithzk.dto.out.PartnerResponse;
import com.ithzk.ifc.DictionaryIfc;
import com.ithzk.ifc.PartnerIfc;
import com.ithzk.common.Detect;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 服务端初始化缓存数据 同步缓存数据
* @author hzk
* @date 2018/3/15
*/
@Component
public class CacheDataSynServerHandle { private static final Logger logger = Logger.getLogger(CacheDataSynServerHandle.class); private String ZK_ADDRESS; /**
* 初始化CacheDataSynServerHandle
*/
public void start(){
new WorkerPool().exec(new Runnable() { @Override
public void run() {
new CacheDataSynServerHandle().init();
}
});
} /**
* 注册监听
*/
public void init() {
ZK_ADDRESS = PropertiesUtil.getValueByBundle("config","zk.address");
logger.info("------register watch path:"+ZK_ADDRESS);
//添加监听
ZkWatcherUtils zkWatcherUtils = new ZkWatcherUtils();
try {
UpdateLocalCacheData change = new UpdateLocalCacheData();
zkWatcherUtils.addWatch(Constants.AbstractZkNodePath.ZK_DICTIONRAY_PATH,change);
} catch (Exception e) {
e.printStackTrace();
logger.error("------register watch error :"+e.getMessage());
} loadZKData();
} /**
* 检查zk中是否有数据
* 没有则初始化zk字典数据
*/
private void loadZKData(){
ZkClientUtils zkClientUtils = new ZkClientUtils();
try {
if(!zkClientUtils.isExists(Constants.AbstractZkNodePath.ZK_DICTIONRAY_PATH)){
List<DictionaryResponse> dicData = getDicData();
String data = JsonUtil.list2json(dicData);
zkClientUtils.create(Constants.AbstractZkNodePath.ZK_DICTIONRAY_PATH, data);
logger.info("------loadZKData success!");
}
} catch (Exception e) {
e.printStackTrace();
logger.error("------loadZKData fail msg:"+e.getMessage());
}finally{
zkClientUtils.close();
}
} /**
* 加载本地缓存
*/
public void loadLocal(){
try {
logger.info("------loadLocal dictionary data--");
List<DictionaryResponse> dataDic = getDicData();
List<PartnerResponse> partnerDic = getPartnerData();
new UpdateLocalCacheData().convert(dataDic,partnerDic);
} catch (Exception e) {
e.printStackTrace();
logger.error("-------------- loadLocal error :"+e.getMessage());
}
} /**
* 重新加载本地缓存
*/
public void reloadLocal() {
loadLocal();
} /**
* 获得字典数据
* @return
*/
private static List<DictionaryResponse> getDicData() {
DictionaryIfc dictionaryIfc = BeanFactoryUtil.getInstance("dictionaryIfc");
Map<String, Object> conditions = new HashMap<String, Object>();
BaseResponse<List<DictionaryResponse>> listBaseResponseDic = dictionaryIfc.selectByExample(conditions);
List<DictionaryResponse> dicList = listBaseResponseDic.getDatat();
return dicList;
} /**
* 获得合作方数据
* @return
*/
private static List<PartnerResponse> getPartnerData() {
PartnerIfc partnerIfc = BeanFactoryUtil.getInstance("partnerIfc");
Map<String, Object> conditions = new HashMap<String, Object>();
BaseResponse<List<PartnerResponse>> listBaseResponsePartner = partnerIfc.selectByExample(conditions);
List<PartnerResponse> partnerList = listBaseResponsePartner.getDatat();
return partnerList;
} static class UpdateLocalCacheData implements IUpdateLocalCacheData { @Override
public void change(Node node) {
try {
logger.info("-------------- zookeeper node change -------------");
List<DictionaryResponse> dataDic = getDicData();
List<PartnerResponse> partnerDic = getPartnerData();
convert(dataDic,partnerDic);
} catch (Exception e) {
e.printStackTrace();
logger.error("-------------- zookeeper node change error :"+e.getMessage());
}
} public void convert(List<DictionaryResponse> dataDic,List<PartnerResponse> partnerDic){
if(!Detect.notEmpty(dataDic)){
return;
}
try {
LoadData.buildLocalCache(dataDic,partnerDic);
logger.info("-------------- server start update local data.... ---------------------");
} catch (Exception e) {
e.printStackTrace();
logger.error("-------------- loadLocal error :"+e.getMessage());
}
} }
}

ZkWatcherUtils

import com.ithzk.common.PropertiesUtil;
import com.ithzk.common.zk.ifc.IUpdateLocalCacheData;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.retry.RetryNTimes;
import org.apache.log4j.Logger; /**
* zookeeper监听工具类
* @author hzk
* @date 2018/3/15
*/
public class ZkWatcherUtils { private static final Logger logger = Logger.getLogger(ZkWatcherUtils.class); private String ZK_ADDRESS; /**
* 添加监听事件
* @param zkPath 路径
* @param updateLocalCacheData 回调
* @throws Exception
*/
public void addWatch(String zkPath,final IUpdateLocalCacheData updateLocalCacheData) throws Exception {
// 连接zk
ZK_ADDRESS = PropertiesUtil.getValueByBundle("config","zk.address");
CuratorFramework client = CuratorFrameworkFactory.newClient(ZK_ADDRESS, new RetryNTimes(10, 5000) );
client.start();
logger.info("----- zk client start success ------"); //注册监听
final NodeCache watcher = new NodeCache(client, zkPath);
watcher.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
if(null != watcher.getCurrentData()){
if(null != updateLocalCacheData){
Node node = new Node(watcher.getCurrentData().getPath(),new String(watcher.getCurrentData().getData(),"utf-8"));
updateLocalCacheData.change(node);
}
logger.info("----- zk node changed, data is: "+ new String(watcher.getCurrentData().getData(),"utf-8"));
}else{
logger.error("----- Node changed, data is null -----");
}
}
}); watcher.start(true);
logger.error("----- Register zk watcher success! -----");
} }
LoadData
package com.blog.cas.common.dic;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.blog.cas.common.constants.Constants;
import com.blog.cas.common.utils.BeanFactoryUtils;
import com.blog.cas.common.utils.Detect;
import com.blog.cas.common.utils.json.JsonUtils;
import com.blog.cas.common.zk.CacheDataSynServerHandle;
import com.blog.cas.common.zk.RetryRecord;
import com.blog.cas.common.zk.ZkClientUtils;
import com.blog.cas.repository.entity.BlogDictionary;
import com.blog.cas.service.IDictionaryService;
import org.apache.log4j.Logger; import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock; /**
* 本地缓存操作类
* @author hzk
* @date 2018/11/14
*/
public class LoadData { private static final Logger logger = Logger.getLogger(LoadData.class); /**
* itemKey value
*/
private static Map<String, BlogDictionary> dicInfoMap = new HashMap<>(); /**
* Id value
*/
private static Map<Integer, BlogDictionary> dicInfoIdMap = new HashMap<>(); private static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private static Lock r = rwl.readLock();
private static Lock w = rwl.writeLock(); /*------------------------------------------ mysql select-------------------------------------------*/ /**
* 通过itemKey从数据库中查询数据
* @param key
* @return {@link BlogDictionary}
*/
private static BlogDictionary getDicByItemKeyWithIfc(String key){
IDictionaryService blogDictionaryService = BeanFactoryUtils.getInstance("dictionaryService");
return blogDictionaryService.selectByItemKey(key);
} /**
* 通过id从数据库中查询数据
* @param id
* @return {@link BlogDictionary}
*/
private static BlogDictionary getDicByIdWithIfc(Integer id){
IDictionaryService blogDictionaryService= BeanFactoryUtils.getInstance("dictionaryService");
return blogDictionaryService.selectByPrimaryKey(id);
} /*------------------------------------------by itemKey-------------------------------------------*/
/**
* 通过itemKey查询字典
* @param key
* @return {@link BlogDictionary}
*/
public static BlogDictionary getDicByItemKey(String key) {
r.lock();
try {
BlogDictionary dictionary = dicInfoMap.get(key);
if (dictionary != null) {
return dictionary;
}
retryBuildLocalCache(dicInfoMap);
BlogDictionary dicByItemKeyWithIfc = getDicByItemKeyWithIfc(key);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc;
}
logger.warn("======Not Found Dic key:" + key);
return null;
}finally {
r.unlock();
} } /**
* 通过itemKey查询字典value
* @param key 字典key
* @param check 是否验证启用
* @return
*/
public static String getDicValueByItemKey(String key,boolean check) {
r.lock();
try {
BlogDictionary dictionary = dicInfoMap.get(key);
if (dictionary != null) {
if(check){
if(Detect.equal(LoadData.getDicIdByItemKey(Constants.AbstractPublicStatus.ENABLE),dictionary.getFrState())){
return dictionary.getItemValue();
}else{
return null;
}
}else{
return dictionary.getItemValue();
}
}
retryBuildLocalCache(dicInfoMap);
BlogDictionary dicByItemKeyWithIfc = getDicByItemKeyWithIfc(key);
if(null != dicByItemKeyWithIfc){
if(check){
if(Detect.equal(LoadData.getDicIdByItemKey(Constants.AbstractPublicStatus.ENABLE),dicByItemKeyWithIfc.getFrState())){
return dicByItemKeyWithIfc.getItemValue();
}else{
return null;
}
}else{
return dicByItemKeyWithIfc.getItemValue();
}
}
logger.warn("======Not Found Dic key:" + key);
return null;
}finally {
r.unlock();
} } /**
* 通过itemKey查询字典value
* @param key 字典key
* @param defaultValue 不存在时设置默认值
* @return
*/
public static String getDicValueByItemKey(String key,String defaultValue){
r.lock();
try {
BlogDictionary dictionary = dicInfoMap.get(key);
if (dictionary != null) {
return dictionary.getItemValue();
}
retryBuildLocalCache(dicInfoMap);
BlogDictionary dicByItemKeyWithIfc = getDicByItemKeyWithIfc(key);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getItemValue();
}
logger.warn("======Not Found Dic key:" + key);
return defaultValue;
} finally {
r.unlock();
}
} /**
* 通过itemKey查询字典ID
* @param key 字典key
* @return
*/
public static int getDicIdByItemKey(String key) {
r.lock();
try {
BlogDictionary dictionary = dicInfoMap.get(key);
if (dictionary != null) {
return Detect.asPrimitiveInt(dictionary.getId());
}
retryBuildLocalCache(dicInfoMap);
BlogDictionary dicByItemKeyWithIfc = getDicByItemKeyWithIfc(key);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getId();
}
logger.warn("======Not Found Dic key:" + key);
return 0;
}finally {
r.unlock();
}
} /**
* 通过itemKey查询字典中文名称
* @param key 字典key
* @return
*/
public static String getDicNameByItemKey(String key) {
r.lock();
try {
BlogDictionary dictionary = dicInfoMap.get(key);
if (dictionary != null) {
return Detect.asString(dictionary.getItemNamecn());
}
retryBuildLocalCache(dicInfoMap);
BlogDictionary dicByItemKeyWithIfc = getDicByItemKeyWithIfc(key);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getItemNamecn();
}
logger.warn("======Not Found Dic key:" + key);
return null;
}finally {
r.unlock();
}
} /*------------------------------------------by id-------------------------------------------*/
/**
* 通过ID查询字典
* @param id 字典ID
* @return {@link BlogDictionary}
*/
public static BlogDictionary getDicById(Integer id) {
r.lock();
try {
BlogDictionary dictionary = dicInfoIdMap.get(id);
if (dictionary != null) {
return dictionary;
} else{
retryBuildLocalCache(dicInfoIdMap);
BlogDictionary dicByItemKeyWithIfc = getDicByIdWithIfc(id);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc;
}
logger.warn("======Not Found Dic id:" + id);
return null;
}
}finally {
r.unlock();
}
} /**
* 通过id查询字典value
* @param id 字典ID
* @return
*/
public static String getDicValueById(Integer id) {
r.lock();
try {
BlogDictionary dictionary = dicInfoIdMap.get(id);
if (dictionary != null) {
return dictionary.getItemValue();
} else{
retryBuildLocalCache(dicInfoIdMap);
BlogDictionary dicByItemKeyWithIfc = getDicByIdWithIfc(id);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getItemValue();
}
logger.warn("======Not Found Dic id:" + id);
return null;
}
}finally {
r.unlock();
}
} /**
* 通过ID查询字典itemKey
* @param id 字典ID
* @return
*/
public static String getDicItemKeyById(Integer id) {
r.lock();
try {
BlogDictionary dictionary = dicInfoIdMap.get(id);
if (dictionary != null) {
return Detect.asString(dictionary.getItemKey());
} else {
retryBuildLocalCache(dicInfoIdMap);
BlogDictionary dicByItemKeyWithIfc = getDicByIdWithIfc(id);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getItemKey();
}
logger.warn("======Not Found Dic id:" + id);
return null;
}
}finally {
r.unlock();
}
} /**
* 通过ID查询字典parentId
* @param id 字典ID
* @return
*/
public static Integer getDicParentIdById(Integer id) {
r.lock();
try {
BlogDictionary dictionary = dicInfoIdMap.get(id);
if (dictionary != null) {
return dictionary.getParentId();
} else {
retryBuildLocalCache(dicInfoIdMap);
BlogDictionary dicByItemKeyWithIfc = getDicByIdWithIfc(id);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getParentId();
}
logger.warn("======Not Found Dic id:" + id);
return null;
}
}finally {
r.unlock();
}
} /**
* 通过ID查询字典中文名称
* @param id 字典ID
* @return
*/
public static String getDicNameById(Integer id) {
r.lock();
try {
BlogDictionary dictionary = dicInfoIdMap.get(id);
if (dictionary != null) {
return Detect.asString(dictionary.getItemNamecn());
} else {
retryBuildLocalCache(dicInfoIdMap);
BlogDictionary dicByItemKeyWithIfc = getDicByIdWithIfc(id);
if(null != dicByItemKeyWithIfc){
return dicByItemKeyWithIfc.getItemNamecn();
}
logger.warn("======Not Found Dic id:" + id);
return null;
}
}finally {
r.unlock();
}
} /*------------------------------------------init data-------------------------------------------*/ /**
* 初始化内存数据
* 字典/合作方
*/
public static void buildLocalCache(List<BlogDictionary> dataDic){
w.lock();
try {
//初始化数据字典
logger.warn("-------------------init dictionary start...---------------------");
for (BlogDictionary blogDictionary : dataDic) {
dicInfoMap.put(Detect.trim(blogDictionary.getItemKey()), blogDictionary);
dicInfoIdMap.put(blogDictionary.getId(), blogDictionary);
}
logger.warn("-------------------init dictionary complete---------------------");
} catch (Exception e){
e.printStackTrace();
logger.warn("-------------------init LoadData error---------------------"+e.getMessage());
} finally{
w.unlock();
}
} /**
* 重试机制
* 若多次发现本地缓存为空 则重新加载本地数据
*/
private static void retryBuildLocalCache(Map<?,BlogDictionary> dataDic){
// 内存中数据为null时 记录获取次数 到达一定次数尝试重试加载缓存
if(!Detect.notEmpty(dataDic)){
logger.warn("------ local cache dic is null -------");
ZkClientUtils zkClientUtils = new ZkClientUtils();
Date currentDate = new Date(System.currentTimeMillis());
try {
if(!zkClientUtils.isExists(Constants.AbstractZkNodePath.ZK_RETRY_RECORD_PATH)){
logger.info("------ init retry record start... -------");
RetryRecord retryRecord = new RetryRecord(Detect.asString(currentDate.getTime()),0);
String data = JsonUtils.object2json(retryRecord);
zkClientUtils.create(Constants.AbstractZkNodePath.ZK_RETRY_RECORD_PATH, data);
logger.info("------ init retry record success -------");
}
String znodeData = zkClientUtils.getZnodeData(Constants.AbstractZkNodePath.ZK_RETRY_RECORD_PATH);
RetryRecord retryRecord = JSONObject.toJavaObject(JSON.parseObject(znodeData), RetryRecord.class);
if(null != retryRecord){
Integer retryCount = retryRecord.getRetryCount();
if(null != retryCount){
if(retryCount % Constants.AbstractZkNodePath.ZK_RETRY_COUNT_REGEX == 1){
// 尝试重新加载本地缓存
new CacheDataSynServerHandle().reloadLocal();
}
retryRecord.setLastRecordTime(Detect.asString(currentDate.getTime()));
retryRecord.setRetryCount(retryCount+1);
String data = JsonUtils.object2json(retryRecord);
zkClientUtils.set(Constants.AbstractZkNodePath.ZK_RETRY_RECORD_PATH, data);
} }
} catch (Exception e) {
e.printStackTrace();
logger.error("------ retry build local cache fail msg:"+e.getMessage());
}finally{
zkClientUtils.close();
}
}
} /**
* 刷新zk字典节点缓存
* @return
*/
public static int renovateZkDicCache(){
ZkClientUtils zkClientUtils = new ZkClientUtils();
int success = 1;
w.lock();
try {
List<BlogDictionary> blogDictionary = CacheDataSynServerHandle.getDicData();
String data = JsonUtils.list2json(blogDictionary);
if(!zkClientUtils.isExists(Constants.AbstractZkNodePath.ZK_DICTIONRAY_PATH)){
zkClientUtils.create(Constants.AbstractZkNodePath.ZK_DICTIONRAY_PATH, data);
logger.info("------renovateZKData success!");
}else{
zkClientUtils.set(Constants.AbstractZkNodePath.ZK_DICTIONRAY_PATH, data);
logger.info("------renovateZKData success!");
}
} catch (Exception e) {
e.printStackTrace();
success = 0;
logger.error("------renovateZKData fail msg:"+e.getMessage());
}finally{
zkClientUtils.close();
w.unlock();
}
return success;
} }

spring.xml

<!-- spring系统启动以后,将laze-init设为false,启动即会加载。会先加载该类 -->
<bean id="beanFactoryUtil" class="com.ithzk.common.BeanFactoryUtil" lazy-init="false"/>
<bean id="initDataListener" class="com.ithzk.common.listener.InitDataListener" lazy-init="false"/>

zookeeper实现项目初始化缓存以及同步监听的更多相关文章

  1. 从jQuery的缓存到事件监听

    不知道大家有没有发现,用jQuery选择器"选择"之后的DOM上会添加jQuery*********属性. <DIV id=d1 jQuery1294122065250=&q ...

  2. clipboard 在 vue 项目中,on 事件监听回调多次执行

    clipboard 定义一个全局变量 import ClipboardJS from "clipboard"; if(clipboard){ clipboard.destroy() ...

  3. Zookeeper Curator 事件监听 - 秒懂

    目录 写在前面 1.1. Curator 事件监听 1.1.1. Watcher 标准的事件处理器 1.1.2. NodeCache 节点缓存的监听 1.1.3. PathChildrenCache ...

  4. 8、Curator的监听机制

    原生的zookeeper的监听API所实现的方法存在一些缺点,对于开发者来说后续的开发会考虑的细节比较多. Curator所实现的方法希望摒弃原声API 的不足,是开发看起来更加的简单,一些重连等操作 ...

  5. Curator的监听机制

    原生的zookeeper的监听API所实现的方法存在一些缺点,对于开发者来说后续的开发会考虑的细节比较多. Curator所实现的方法希望摒弃原声API 的不足,是开发看起来更加的简单,一些重连等操作 ...

  6. Redis集群环境下的键值空间监听事件实现方案

    一直想记录工作中遇到的问题和解决的方法,奈何没有找到一方乐土,最近经常反思,是否需要记录平时的点滴,后台还是决定下定决心记录一些,以便以后用到的时候找不着,实现这样的一个功能主要也是业务所需要的. 需 ...

  7. Android Editext监听光标位置

    因为项目需要,需要实时监听光标的位置变化,网上提出的用TextWatcher和onTouchListener中调用contentText.getSelectionStart()都是获取的上一次位置. ...

  8. bluetooth-蓝牙事件监听

    今天在做项目的时候,需要监听一个蓝牙耳机的连接状态.就写了一个小的测试方法.记录如下 看代码 这要处理的是蓝牙监听事件 package com.example.alert; import androi ...

  9. ReactNative实现通知监听事件

    事例1: 只在rn里面发送和接受消息. A界面: import {DeviceEventEmitter} from 'react-native'; //... componentDidMount(){ ...

随机推荐

  1. python re库的正则表达式学习笔记

    1. 安装 默认已经安装好了python环境了 re库是python3的核心库,不需要pip install,直接import就行 2. 最简单的模式 字符本身就是最简单的模式 比如:'A', 'I ...

  2. Linux禁止普通用户su至root

    linux系统为了限制权限,有时候需要禁止普通用户su到root用户 为禁止普通用户su至root,需要分别修改/etc/pam.d/su和/etc/login.defs两个配置文件. 二.详细配置 ...

  3. Spring MVC 以.html为后缀名访问获取数据,报406 Not Acceptable错误

    转载,感谢这位博主,有自己的添加. 如题,最近以spring mvc作为后台框架,前端异步获取数据时(.html为后缀名的访问方式),报406 Not Acceptable错误.当初都不知道啥原因,前 ...

  4. 打包github上的项目,并在本地使用

    在GitHub上去找工具并把地址克隆下来 在本地创建一个文件夹,文件夹内右击 (建议路径为英文,并保证本机有github的软件: https://jingyan.baidu.com/article/9 ...

  5. 推荐多线程下载工具axel替代wget

    在爬数据的时候很多时候需要下载文件比如压缩文件,音频,视频,图片等等,这些文件通常有一个请求的url,这个时候使用request模块或者urllib模块都很慢,而且很不稳定,这个时候使用wget或者a ...

  6. vue的环境安装(一node环境)

    话不多说都知道vue是基于node环境的.肯定是要安装node环境的 1.node官网下载https://nodejs.org/en/download/对应的版本我的是win的 2.双击下载下来的安装 ...

  7. 【腾讯海纳】系统未发布时如何获取获取property_id在本地进行测试?

    有现成https协议域名使用者,可忽略此文. 直接先上图,明白的人看一眼图片就知道怎么拿了,如下所示: 解释说明: 在完成添加套件,以及测试应用的前提下,按如下操作流程: 1.访问路径:登录“海纳开发 ...

  8. C++ 初步

    c++新特性: 1. 初始化方法: 复制初始化 int x=1024; 直接初始化 int x (1024); 2.变量随用随定义 3.增加bool数据类型 输入输出: cout<<x; ...

  9. webpack配置非CMD规范的模块

    一.前言 webpack在配置多页面开发的时候 ,发现用 import 导入 Zepto 时,会报 Uncaught TypeError: Cannot read property 'createEl ...

  10. npm修改淘宝原

    //修改之前查看一下npm config get registry https://registry.npmjs.org/ //设置源npm config set registry https://r ...