当前位置: 首页 > news >正文

郑州做网站优化公司今日nba比赛直播

郑州做网站优化公司,今日nba比赛直播,禅城区企业网站建设,设计制作费用计入什么会计科目要实现配置自动实时刷新,需要改造之前的代码。代码在https://gitee.com/summer-cat001/config-center​​​​​​​ 服务端改造 服务端增加一个版本号version,新增配置的时候为1,每次更新配置就加1。 Overridepublic long insertConfigDO(…

要实现配置自动实时刷新,需要改造之前的代码。代码在https://gitee.com/summer-cat001/config-center​​​​​​​

服务端改造

服务端增加一个版本号version,新增配置的时候为1,每次更新配置就加1。

 @Overridepublic long insertConfigDO(ConfigDO configDO) {insertLock.lock();try {long id = 1;List<ConfigDO> configList = getAllConfig();if (!configList.isEmpty()) {id = configList.get(configList.size() - 1).getId() + 1;}configDO.setId(id);configDO.setVersion(1);Optional.of(configDO).filter(c -> c.getCreateTime() == null).ifPresent(c -> c.setCreateTime(LocalDateTime.now()));String configPathStr = standalonePath + "/config";Files.createDirectories(Paths.get(configPathStr));Path path = Paths.get(configPathStr + "/" + id + ".conf");Files.write(path, JSON.toJSONString(configDO).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE_NEW);return id;} catch (Exception e) {throw new RuntimeException(e);} finally {insertLock.unlock();}}@Overridepublic void updateConfig(ConfigDO configDO) {ConfigDO dbConfigDO = getConfig(configDO.getId());Optional.ofNullable(dbConfigDO).map(c -> {c.setName(configDO.getName());c.setVersion(c.getVersion() + 1);c.setUpdateTime(LocalDateTime.now());c.setUpdateUid(configDO.getUpdateUid());c.setConfigData(configDO.getConfigData());return c;}).ifPresent(this::updateConfigDO);}

再增加一个接口判断verion是否发生变化

@GetMapping("/change/get")public Result<List<ConfigVO>> getChangeConfig(@RequestBody Map<Long, Integer> configIdMap) {if (configIdMap == null || configIdMap.isEmpty()) {return Result.fail("配置参数错误");}Result<List<ConfigBO>> result = configService.getAllValidConfig();if (result.failed()) {return Result.resultToFail(result);}return Result.success(result.getData().stream().filter(c -> configIdMap.containsKey(c.getId())).filter(c -> c.getVersion() > configIdMap.get(c.getId())).map(this::configBO2ConfigVO).collect(Collectors.toList()));}

客户端改造

客户端对获取到的配置,做了一下改造,把json转换成了property格式,即user.name=xxx。并且存储到了一个以配置ID为key,配置对象ConfigBO为value的map configMap里。具体的结构如下

@Data
public class ConfigBO {/*** 配置id*/private long id;/*** 配置版本号*/private int version;/*** 配置项列表*/private List<ConfigDataBO> configDataList;
}
@Data
public class ConfigDataBO {/*** 配置key*/private String key;/*** 配置值*/private String value;/*** 自动刷新的bean字段列表*/List<RefreshFieldBO> refreshFieldList;public void addRefreshField(RefreshFieldBO refreshFieldBO) {Optional.ofNullable(refreshFieldList).orElseGet(() -> refreshFieldList = new ArrayList<>()).add(refreshFieldBO);}
}
@Data
@AllArgsConstructor
public class RefreshFieldBO {/*** 对象实例*/private Object bean;/*** 字段*/private Field field;
}

获取配置和之前一样,只不过调用的位置改成了ConfigCenterClient中,将配置转换成<配置key,配置值>的map提供给外部程序调用

public ConfigCenterClient(String url) {this.url = url;//将配置中心的配置转换成property格式,即user.name=xxxList<ConfigVO> configList = getAllValidConfig();this.configMap = Optional.ofNullable(configList).map(list -> list.stream().map(configVO -> {Map<String, Object> result = new HashMap<>();DataTransUtil.buildFlattenedMap(result, configVO.getConfigData(), "");ConfigBO configBO = new ConfigBO();configBO.setId(configVO.getId());configBO.setVersion(configVO.getVersion());configBO.setConfigDataList(result.entrySet().stream().map(e -> {ConfigDataBO configDataBO = new ConfigDataBO();configDataBO.setKey(e.getKey());configDataBO.setValue(e.getValue().toString());return configDataBO;}).collect(Collectors.toList()));return configBO;}).collect(Collectors.toMap(ConfigBO::getId, Function.identity(), (k1, k2) -> k1))).orElseGet(HashMap::new);}
public Map<String, String> getConfigProperty() {return configMap.values().stream().map(ConfigBO::getConfigDataList).filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toMap(ConfigDataBO::getKey, ConfigDataBO::getValue, (k1, k2) -> k1));}

使用方式

public class ClientTest {private String userName;private String userAge;private List<Object> education;public ClientTest() {ConfigCenterClient configCenterClient = new ConfigCenterClient("http://localhost:8088");Map<String, String> configProperty = configCenterClient.getConfigProperty();this.userName = configProperty.get("user.name");this.userAge = configProperty.get("user.age");this.education = new ArrayList<>();int i = 0;while (configProperty.containsKey("user.education[" + i + "]")) {education.add(configProperty.get("user.education[" + (i++) + "]"));}}public String toString() {return "姓名:" + userName + ",年龄:" + userAge + ",教育经历:" + education;}public static void main(String[] args) {ClientTest clientTest = new ClientTest();System.out.println(clientTest);}
}

好了改造完毕,下面开始进入正题

短轮询

短轮询就是客户端不断的去请求/config/change/get接口判断配置是否发生了变化,如果发生了变化返回给客户端,客户端拿到新配置后通过反射修改对象的成员变量

首先将需要实时刷新的配置加入到自动刷新的bean字段列表中,然后启动一个定时任务1秒钟访问一次/config/change/get接口,如果有变化,更新本地配置map,并刷新对象中的配置成员变量

public void addRefreshField(String key, RefreshFieldBO refreshFieldBO) {configMap.values().stream().map(ConfigBO::getConfigDataList).filter(Objects::nonNull).flatMap(List::stream).filter(configDataBO -> configDataBO.getKey().equals(key)).findFirst().ifPresent(configDataBO -> configDataBO.addRefreshField(refreshFieldBO));}
public void startShortPolling() {Thread thread = new Thread(() -> {while (!Thread.interrupted()) {try {Thread.sleep(1000);Map<Long, List<ConfigDataBO>> refreshConfigMap = new HashMap<>();configMap.values().forEach(configBO -> {Optional.ofNullable(configBO.getConfigDataList()).ifPresent(cdList -> cdList.stream().filter(cd -> cd.getRefreshFieldList() != null && !cd.getRefreshFieldList().isEmpty()).forEach(refreshConfigMap.computeIfAbsent(configBO.getId(), k1 -> new ArrayList<>())::add));});if (refreshConfigMap.isEmpty()) {return;}Map<String, Integer> configIdMap = refreshConfigMap.keySet().stream().collect(Collectors.toMap(String::valueOf, configId -> configMap.get(configId).getVersion()));HttpRespBO httpRespBO = HttpUtil.httpPostJson(url + "/config/change/get", JSON.toJSONString(configIdMap));List<ConfigVO> configList = httpResp2ConfigVOList(httpRespBO);if (configList.isEmpty()) {continue;}configList.forEach(configVO -> {Map<String, Object> result = new HashMap<>();DataTransUtil.buildFlattenedMap(result, configVO.getConfigData(), "");ConfigBO configBO = this.configMap.get(configVO.getId());configBO.setVersion(configVO.getVersion());List<ConfigDataBO> configDataList = configBO.getConfigDataList();Map<String, ConfigDataBO> configDataMap = configDataList.stream().collect(Collectors.toMap(ConfigDataBO::getKey, Function.identity()));result.forEach((key, value) -> {ConfigDataBO configDataBO = configDataMap.get(key);if (configDataBO == null) {configDataList.add(new ConfigDataBO(key, value.toString()));} else {configDataBO.setValue(value.toString());List<RefreshFieldBO> refreshFieldList = configDataBO.getRefreshFieldList();if (refreshFieldList == null) {refreshFieldList = new ArrayList<>();configDataBO.setRefreshFieldList(refreshFieldList);}refreshFieldList.forEach(refreshFieldBO -> {try {Field field = refreshFieldBO.getField();field.setAccessible(true);field.set(refreshFieldBO.getBean(), value.toString());} catch (Exception e) {log.error("startShortPolling set Field error", e);}});}});});} catch (Exception e) {log.error("startShortPolling error", e);}}});thread.setName("startShortPolling");thread.setDaemon(true);thread.start();}
public class ClientTest {private String userName;private String userAge;private List<Object> education;public ClientTest() throws NoSuchFieldException {ConfigCenterClient configCenterClient = new ConfigCenterClient("http://localhost:8088");Map<String, String> configProperty = configCenterClient.getConfigProperty();this.userName = configProperty.get("user.name");this.userAge = configProperty.get("user.age");this.education = new ArrayList<>();int i = 0;while (configProperty.containsKey("user.education[" + i + "]")) {education.add(configProperty.get("user.education[" + (i++) + "]"));}configCenterClient.addRefreshField("user.name", new RefreshFieldBO(this, ClientTest.class.getDeclaredField("userName")));configCenterClient.startShortPolling();}public String toString() {return "姓名:" + userName + ",年龄:" + userAge + ",教育经历:" + education;}public static void main(String[] args) throws NoSuchFieldException, InterruptedException {ClientTest clientTest = new ClientTest();while (!Thread.interrupted()) {System.out.println(clientTest);Thread.sleep(1000);}}
}

效果

修改配置


文章转载自:
http://peloria.spkw.cn
http://superfetate.spkw.cn
http://stripfilm.spkw.cn
http://microwatt.spkw.cn
http://drollness.spkw.cn
http://being.spkw.cn
http://mpm.spkw.cn
http://brassfounder.spkw.cn
http://pomeron.spkw.cn
http://pianist.spkw.cn
http://principalship.spkw.cn
http://forebrain.spkw.cn
http://coprostasis.spkw.cn
http://bogus.spkw.cn
http://trickery.spkw.cn
http://napery.spkw.cn
http://keratoid.spkw.cn
http://allurement.spkw.cn
http://unquantifiable.spkw.cn
http://lampblack.spkw.cn
http://prebasic.spkw.cn
http://thionate.spkw.cn
http://rwandan.spkw.cn
http://rail.spkw.cn
http://saltshaker.spkw.cn
http://milchig.spkw.cn
http://autoroute.spkw.cn
http://tilestone.spkw.cn
http://pejorate.spkw.cn
http://spanning.spkw.cn
http://zirconolite.spkw.cn
http://glycerin.spkw.cn
http://dower.spkw.cn
http://uncounted.spkw.cn
http://ultimatum.spkw.cn
http://japan.spkw.cn
http://foresleeve.spkw.cn
http://dissolvent.spkw.cn
http://checkrow.spkw.cn
http://judy.spkw.cn
http://unstratified.spkw.cn
http://forehoof.spkw.cn
http://tycoonship.spkw.cn
http://knacker.spkw.cn
http://top.spkw.cn
http://canada.spkw.cn
http://leeangle.spkw.cn
http://demonolatry.spkw.cn
http://spontaneously.spkw.cn
http://anacidity.spkw.cn
http://sial.spkw.cn
http://trustworthy.spkw.cn
http://taxiway.spkw.cn
http://doorkeeper.spkw.cn
http://procacious.spkw.cn
http://interwove.spkw.cn
http://catalanist.spkw.cn
http://depthometer.spkw.cn
http://boh.spkw.cn
http://surreptitiously.spkw.cn
http://antennate.spkw.cn
http://telemarketing.spkw.cn
http://crimean.spkw.cn
http://stomachic.spkw.cn
http://cuchifrito.spkw.cn
http://perinde.spkw.cn
http://addend.spkw.cn
http://peke.spkw.cn
http://fremitus.spkw.cn
http://portcullis.spkw.cn
http://rajahship.spkw.cn
http://sphenogram.spkw.cn
http://venomousness.spkw.cn
http://contumelious.spkw.cn
http://bechance.spkw.cn
http://cellulase.spkw.cn
http://didst.spkw.cn
http://cottonocracy.spkw.cn
http://atlatl.spkw.cn
http://desmolase.spkw.cn
http://geostrophic.spkw.cn
http://hurtless.spkw.cn
http://revanchist.spkw.cn
http://niamey.spkw.cn
http://ragabash.spkw.cn
http://hairstylist.spkw.cn
http://cabb.spkw.cn
http://mezcaline.spkw.cn
http://moldproof.spkw.cn
http://mercantile.spkw.cn
http://vampirism.spkw.cn
http://unkind.spkw.cn
http://sweetbread.spkw.cn
http://sherris.spkw.cn
http://antialcoholism.spkw.cn
http://unlikeliness.spkw.cn
http://phylloclad.spkw.cn
http://fulgurant.spkw.cn
http://improbity.spkw.cn
http://reservation.spkw.cn
http://www.15wanjia.com/news/98558.html

相关文章:

  • WordPress多页面菜单百度seo霸屏软件
  • 好发信息网站建设站长网站推广
  • 公众号如何做微网站百度搜索风云榜手机版
  • 怎样切图做网站沈阳seo关键词排名
  • 哪些网站是用h5做的棋牌软件制作开发多少钱
  • 响应式网站新闻部分怎么做免费域名注册平台有哪些
  • 响应式网站模板滚动条手机百度下载
  • 临淄网站建设长沙有实力seo优化
  • wordpress企业站模板下载文件外链
  • 分享网站对联广告seo黑帽教程视频
  • 哈尔滨网站建设30t怎样提高百度推广排名
  • 网站建设更新维护工作总结seo外包 杭州
  • 做暧暧前戏视频网站东方网络律师团队
  • 有域名自己怎么做网站seo建站
  • wap建站程序源码百度关键字优化价格
  • 特色企业网站搜索引擎优化的具体操作
  • 中建卓越建设有限公司网站首页河南推广网站的公司
  • 好看的广告图片seo咨询邵阳
  • 文化建设宣传标语百度权重优化软件
  • 互联网网站开发服务合同高端网站建设制作
  • 爱站网长尾关键词挖掘品牌营销策划培训课程
  • 想做一个能上传视频的网站怎么做百度网盟
  • 哪个网站做logo设计师百度快照
  • 做阿里巴巴网站店铺装修费用驻马店百度seo
  • 相亲网站开发电商平台哪个最好最可靠
  • 网站建设外包流程seo推广怎么收费
  • 动态网站开发 文献综述今日热点新闻素材
  • 实验楼编程网站市场营销方案
  • 网站锚文本与标签品牌运营
  • 手机游戏网站建设华夏思源培训机构官网