简历免费在线制作网站,wordpress内容登陆后可见,wordpress 显示文章发布时间,外贸流程优化这一篇文章比较简单#xff0c;就是一个增删改查的服务端和一个获取配置的客户端#xff0c;旨在搭建一个简单的配置中心架构#xff0c;代码在 https://gitee.com/summer-cat001/config-center
服务端
服务端选择用springboot 2.7.14搭建#xff0c;设计了4个接口/confi…这一篇文章比较简单就是一个增删改查的服务端和一个获取配置的客户端旨在搭建一个简单的配置中心架构代码在 https://gitee.com/summer-cat001/config-center
服务端
服务端选择用springboot 2.7.14搭建设计了4个接口/config/insert、/config/update、/config/delete、/config/get。
Controller层
Controller层做了请求参数的校验和对服务层的转发
RestController
RequestMapping(/config)
public class ConfigController {Autowiredprivate ConfigService configService;PostMapping(/insert)public ResultVoid insertConfig(RequestBody ConfigVO configVO) {ResultConfigBO result checkOpConfig(configVO);if (result.failed()) {return Result.resultToFail(result);}return configService.insertConfig(result.getData());}PostMapping(/update)public ResultVoid updateConfig(RequestBody ConfigVO configVO) {ResultConfigBO result checkOpConfig(configVO);if (result.failed()) {return Result.resultToFail(result);}ConfigBO configBO result.getData();long id configVO.getId();if (id 0) {return Result.fail(配置id错误);}configBO.setId(id);return configService.updateConfig(configBO);}PostMapping(/delete)public ResultVoid delConfig(RequestBody ConfigVO configVO) {long id configVO.getId();if (id 0) {return Result.fail(配置id错误);}return configService.delConfig(id, 0L);}GetMapping(/get)public ResultListConfigVO getAllValidConfig() {ResultListConfigBO result configService.getAllValidConfig();if (result.failed()) {return Result.resultToFail(result);}return Result.success(result.getData().stream().map(configBO - {ConfigVO configVO new ConfigVO();configVO.setId(configBO.getId());configVO.setName(configBO.getName());configVO.setConfigData(configBO.getConfigData());configVO.setCreateTime(DateUtil.date2str1(configBO.getCreateTime()));return configVO;}).collect(Collectors.toList()));}private ResultConfigBO checkOpConfig(ConfigVO configVO) {String name configVO.getName();if (name null || (name name.trim()).length() 0) {return Result.fail(配置名不能为空);}JSONObject configData configVO.getConfigData();if (configData null) {return Result.fail(配置内容不能为空);}ConfigBO configBO new ConfigBO();configBO.setName(name);configBO.setConfigData(configData);return Result.success(configBO);}
}
Service层
Service层做了数据的转换和对dao层的调用对于这个配置中心数据的存储我做了两个模式1是单机模式2是集群模式。简单的来说就是一个存在数据库中一个存在本地。根据配置文件中的config.center.mode来指定使用哪种模式
Service
public class ConfigServiceImpl implements ConfigService {private ConfigDAO configDAO;Autowiredprivate LocalConfigDAO localConfigDAO;Value(${config.center.mode:0})private int configCenterMode;PostConstructpublic void init() {ConfigCenterModeEnum configCenterModeEnum ConfigCenterModeEnum.getEnum(configCenterMode);if (configCenterModeEnum null) {throw new IllegalArgumentException(配置config.center.mode错误);}if (configCenterModeEnum ConfigCenterModeEnum.STANDALONE) {this.configDAO localConfigDAO;}}Overridepublic ResultVoid insertConfig(ConfigBO configBO) {ListConfigDO configList configDAO.getAllValidConfig();if (configList.stream().anyMatch(c - c.getName().equals(configBO.getName()))) {return Result.fail(配置名重复);}ConfigDO configDO new ConfigDO();configDO.setName(configBO.getName());configDO.setConfigData(configBO.getConfigData().toJSONString());configDAO.insertConfigDO(configDO);return Result.success(null);}Overridepublic ResultVoid updateConfig(ConfigBO configBO) {ConfigDO configDO new ConfigDO();configDO.setId(configBO.getId());configDO.setName(configBO.getName());configDO.setConfigData(configBO.getConfigData().toJSONString());configDAO.updateConfig(configDO);return Result.success(null);}Overridepublic ResultVoid delConfig(long id, long updateUid) {configDAO.delConfig(id, updateUid);return Result.success(null);}Overridepublic ResultListConfigBO getAllValidConfig() {ListConfigDO configList configDAO.getAllValidConfig();return Result.success(configList.stream().map(configDO - {ConfigBO configBO new ConfigBO();configBO.setId(configDO.getId());configBO.setName(configDO.getName());configBO.setCreateTime(configDO.getCreateTime());configBO.setConfigData(JSON.parseObject(configDO.getConfigData()));return configBO;}).collect(Collectors.toList()));}
}
DAO层
DAO层提供了一个接口com.config.center.dao.ConfigDAO。单机和集群模式分别实现这个接口例如单机模式是com.config.center.dao.impl.LocalConfigDAO实现类集群模式就是访问数据库大家估计都用吐了这个就不多介绍了。 单机模式就是将配置文件存储到本地的一个路径中这个路径根据配置文件的config.center.standalone.path配置来指定保存的是以配置id为文件名.conf为后缀的文件。其中id是从1开始自增增加配置接口用了锁所以id不会重复
Slf4j
Repository
public class LocalConfigDAO implements ConfigDAO {private final Lock insertLock new ReentrantLock();Value(${config.center.standalone.path})private String standalonePath;Overridepublic long insertConfigDO(ConfigDO configDO) {insertLock.lock();try {long id 1;ListConfigDO configList getAllConfig();if (!configList.isEmpty()) {id configList.get(configList.size() - 1).getId() 1;}configDO.setId(id);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.setUpdateTime(LocalDateTime.now());c.setUpdateUid(configDO.getUpdateUid());c.setConfigData(configDO.getConfigData());return c;}).ifPresent(this::updateConfigDO);}Overridepublic void delConfig(long id, long updateUid) {ConfigDO dbConfigDO getConfig(id);Optional.ofNullable(dbConfigDO).map(c - {c.setDeleted(true);c.setUpdateTime(LocalDateTime.now());c.setUpdateUid(updateUid);return c;}).ifPresent(this::updateConfigDO);}Overridepublic ConfigDO getConfig(long id) {ListConfigDO configList getAllConfig();return configList.stream().filter(c - c.getId() id).findFirst().orElse(null);}Overridepublic ListConfigDO getAllValidConfig() {return getAllConfig().stream().filter(c - !c.isDeleted()).collect(Collectors.toList());}Overridepublic ListConfigDO getAllConfig() {File[] files;File folder new File(standalonePath /config);if (!folder.exists() || (files folder.listFiles()) null) {return new ArrayList();}return Arrays.stream(files).map(File::getAbsolutePath).filter(p - p.endsWith(.conf)).map(this::buildConfigDO).filter(Objects::nonNull).sorted(Comparator.comparing(ConfigDO::getId)).collect(Collectors.toList());}private synchronized ConfigDO buildConfigDO(String path) {try {byte[] bytes Files.readAllBytes(Paths.get(path));String json new String(bytes, StandardCharsets.UTF_8);return JSON.parseObject(json, ConfigDO.class);} catch (Exception e) {log.error(buildConfigDO error,path:{}, path, e);return null;}}private synchronized void updateConfigDO(ConfigDO configDO) {Path path Paths.get(standalonePath /config/ configDO.getId() .conf);if (Files.exists(path)) {try {Files.write(path, JSON.toJSONString(configDO).getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE);} catch (IOException e) {log.error(updateConfigDO error configDO:{}, configDO, e);}}}
}效果
到这里就已经完成了服务端的构建了简单吧下面看看效果
新增配置 获取所有有效配置 修改配置 删除配置 客户端
客户端就更简单了就是在启动时通过http调用上面的/config/get接口获取配置并且赋值给对象的成员变量之后直接使用这个成员变量即可
public class ConfigCenterClient {/*** 服务端地址*/private String url;public ListConfigVO getAllValidConfig() {HttpRespBO httpRespBO HttpUtil.httpGet(url /config/get);if (!httpRespBO.success()) {throw new IllegalArgumentException(获取配置失败code: httpRespBO.getCode() ,msg: httpRespBO.getMessage());}if (httpRespBO.getBody() null) {throw new IllegalArgumentException(获取配置失败 body is nullcode: httpRespBO.getCode() ,msg: httpRespBO.getMessage());}Result? result JSON.parseObject(new String(httpRespBO.getBody(), StandardCharsets.UTF_8), Result.class);if (result.failed()) {throw new IllegalArgumentException(获取配置失败 result: result);}return JSON.parseArray(JSON.toJSONString(result.getData()), ConfigVO.class);}public void setUrl(String url) {this.url url;}}
public class ClientTest {private String userName;private String userAge;private ListObject education;public ClientTest() {ConfigCenterClient configCenterClient new ConfigCenterClient();configCenterClient.setUrl(http://localhost:8088);ListConfigVO configList configCenterClient.getAllValidConfig();configList.stream().map(ConfigVO::getConfigData).map(c - c.getJSONObject(user)).findFirst().ifPresent(user - {this.userName user.getString(name);this.userAge user.getString(age);this.education user.getJSONArray(education);});}public String toString() {return 姓名: userName ,年龄: userAge ,教育经历: education;}public static void main(String[] args) {ClientTest clientTest new ClientTest();System.out.println(clientTest);}
}这样整个配置中心的简单版本就完成了不过这样只是在new对象的时候设置了配置的值但是如果配置中心的配置发生变化后客户端是无法感知的为了解决这个问题需要加入配置自动刷新功能这个我们在下一篇文章中介绍。