前言

在前两次的 cicada 版本中其实还不支持读取配置文件,比如对端口、路由的配置。

因此我按照自己的想法创建了一个 issue ,也收集到了一些很不错的建议。

最终其实还是按照我之前的想法来做了这个配置管理。

同时将 cicada 升级到了 v1.0.2

目标

在做之前是要把需求想好,到底怎样的一个配置管理是对开发人员来说比较友好的?

我认为有以下几点:

  • 可以自定义配置,并且支持不同的环境(开发、测试、生产)。
  • 使用灵活。对使用者来说不要有太多的束缚。

理论上来说配置这个东西应当完全独立出来,由一个配置中心来负责管理并且这样可以与应用解耦。

不过这样的实现和当前 cicada 的定义有些冲突,我想尽量小的依赖第三方组件并可以完全独立运行。

因此基于这样的情况便有了以下的实现。

使用

在看实现之前先看看基于目前的配置管理如何在业务中使用起来。

结合现在大家使用 SpringBoot 的习惯,cicada 默认会读取 classpath 下的 application.properties 配置文件。并且会默认读取其中的应用端口以及初始路由地址。

同时也新增了一个 api。

public class MainStart {

    public static void main(String[] args) throws Exception {
CicadaServer.start(MainStart.class,"/cicada-example") ;
}
} public class MainStart { public static void main(String[] args) throws Exception {
CicadaServer.start(MainStart.class) ;
}
}

这样在不传默认地址的时候 cicada 会从 application.properties 中读取。

考虑到后面可维护的情况,cicada 也支持配置各种不同的配置文件。

使用也比较简单,只需要继承 cicada 提供的一个抽象类即可。

public class KafkaConfiguration extends AbstractCicadaConfiguration {

    public KafkaConfiguration() {
super.setPropertiesName("kafka.properties");
} } public class RedisConfiguration extends AbstractCicadaConfiguration { public RedisConfiguration() {
super.setPropertiesName("redis.properties");
} }

按照这样的配置也会默认从 classpath 读取这两个配置文件。

当然这里有个前提:代码里配置的文件名必须得和配置文件名称相同。

那如何在业务中读取这两个配置文件的内容呢?

这也简单,代码一看就懂:

  • 首先需要通过 ConfigurationHolder 获取各自不同配置的管理对象(需要显式指定类类型)。
  • 通过 get() 方法直接获取配置。
  • 同时也支持获取 application.properties 里的配置。

同时为了支持在不同环境的使用,当配置了启动参数将会优先读取。

-Dapplication.properties=/xx/application.properties
-Dkafka.properties=/xx/kakfa.properties
-Dredis.properties=/xx/redis.properties

这样算是基本实现了上述的配置要求。

实现

要实现以上的功能有几个核心点:

  1. 加载所有配置文件。
  2. 将不同的配置文件用不同的对象进行管理。
  3. 提供简易的接口使用。

由于 cicada 需要支持多个配置文件,所有需要定义一个抽象类供所有的配置管理实现。

定义比较简单,其中有两个重要的成员变量:

  • 文件名称:用于初始化时通过名称加载配置文件。
  • Properties 其实就是一个 Map 结构的缓存,用于存放所有的配置。当然对外提供的查询是基于它的。

接着就是在初始化时需要找出所有继承了 AbstractCicadaConfiguration 的类。

查询出来之后自然是要进行遍历同时反射创建对象。

由于之前已经调用了

super.setPropertiesName("redis.properties");

来赋值配置文件名称,所以还需要在遍历过程中将 Properties 进行赋值。

同时在这里也体现出优先读取的是 VM 启动参数中的配置文件。

String systemProperty = System.getProperty(conf.getPropertiesName());

需要额外提一点的是:在查找所有用户自定义的配置管理类时需要手动将 cicada 内置的

ApplicationConfiguration 加入其中。

因为使用应用的包名通过反射是查询不出该类的。

保存自定义配置管理

为了方便用户在使用时候可以随意的读取各个配置文件,所以还需要将反射创建的对象保存到一个内部缓存中,核心代码就是上上图中的这段代码:

// add configuration cache
ConfigurationHolder.addConfiguration(aClass.getName(), conf);

其中 ConfigurationHolder 的定义如下。

其实也是利用一个 Map 来存放这些对象。

这样在使用时候只需要取出即可。

KafkaConfiguration configuration = (KafkaConfiguration) getConfiguration(KafkaConfiguration.class);
String brokerList = configuration.get("kafka.broker.list");

重构

本次升级同时还重构了部分代码,比如启动类。

现在看上去要清爽和直接的多:

其中也有一点需要注意的地方。

大家如果查看日志的话会发现应用启动之后会打印本次的耗时,自然就是在启动时候记录一个时间,初始化完毕之后记录一个即可。

在之前的实现中由于都是在一个方法内,所以直接使用就行了。

但现在优化之后跨越了不同的方法和类,难道要把时间作为参数在各个方法之前传递嘛?

那未免太不优雅了。

所以 ThreadLocal 就有了发挥余地。

在初始化的方法中我将当前时间写入:

ThreadLocalHolder.setLocalTime(System.currentTimeMillis());

在最后记录日志的地方直接取出比较即可:

这样使用起来就完全不需要管什么参数传递了。

同时 ThreadLocalHolder 的定义:

这里还是有一点需要注意,在这种长生命周期的容器中一定得要记得及时清除

我这里的时间在查询一次之后就不用了,所以完全放心的在 getLocalTime() 方法中删掉。

总结

这就是本次 v1.0.2 中的升级内容,包含了配置支持以及代码重构。其中有些内容我觉得对接触少的同学来说还是挺有帮助的。

关于上两次的版本介绍请查看这里:

还没点关注的朋友可以点波关注:

https://github.com/TogetherOS/cicada

也欢迎大家参与一起维护!。

同时后续关于 cicada 的更新会放慢一些。会介绍一些平时实战相关的内容,比如 Kafka 之类的,请持续关注。

你的点赞与转发是最大的支持。

「造个轮子」——cicada 设计一个配置模块的更多相关文章

  1. 「造个轮子」——cicada 源码分析

    前言 两天前写了文章<「造个轮子」--cicada(轻量级 WEB 框架)> 向大家介绍了 cicada 之后收到很多反馈,也有许多不错的建议. 同时在 GitHub 也收获了 80 几颗 ...

  2. 「造个轮子」——cicada(轻量级 WEB 框架)

    前言 俗话说 「不要重复造轮子」,关于是否有必要不再本次讨论范围. 创建这个项目的主要目的还是提升自己,看看和知名类开源项目的差距以及学习优秀的开源方式. 好了,现在着重来谈谈 cicada 这个项目 ...

  3. 「造个轮子」——设计 HTTP 请求全局上下文

    前言 本次 Cicada 已经更新到了 v1.0.3. 主要是解决了两个 issue,#9(Boss线程数好像设置有误 ) #8(怎么返回纯字符串内容不要JSON格式?). 所以本次的主要更新为: C ...

  4. 「Netty实战 02」手把手教你实现自己的第一个 Netty 应用!新手也能搞懂!

    大家好,我是 「后端技术进阶」 作者,一个热爱技术的少年. 很多小伙伴搞不清楚为啥要学习 Netty ,今天这篇文章开始之前,简单说一下自己的看法: @ 目录 服务端 创建服务端 自定义服务端 Cha ...

  5. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...

  6. 力扣Leetcode 1248. 统计「优美子数组」

    统计「优美子数组」 给你一个整数数组 nums 和一个整数 k. 如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」. 请返回这个数组中「优美子数组」的数目. 示例 ...

  7. 零元学Expression Design 4 - Chapter 3 看小光被包围了!!如何活用「Text On Path」设计效果

    原文:零元学Expression Design 4 - Chapter 3 看小光被包围了!!如何活用「Text On Path」设计效果 本章将教大家如何活用「Text On Path」,做出文绕图 ...

  8. 迄今为止最硬核的「Java8时间系统」设计原理与使用方法

    为了使本篇文章更容易让读者读懂,我特意写了上一篇<任何人都需要知道的「世界时间系统」构成原理,尤其开发人员>的科普文章.本文才是重点,绝对要读,走起! Java平台时间系统的设计方案 几乎 ...

  9. 教你用python搭建一个「生活常识解答」机器人

    今天教大家如何用Python爬虫去搭建一个「生活常识解答」机器人. 思路:这个机器人主要是依托于"阿里达摩院发布的语言模型PLUG",通过爬虫的方式,发送post请求(提问),然后 ...

随机推荐

  1. AngualrJS之自定义指令

    一.指令 指令directive是AngularJS的核心之一 包括 - 用于扩展HTML元素.属性的指令 - 执行特定功能的指令 - 自定义指令 内置指令基本上都是以ng-开头 二.内置指令 1.属 ...

  2. Spark内核

    一些名词概念 AM : ApplicationMaster RM : ResourceManager NM : NodeManager Backend : 后台 RpcEnv : RPC 进程和进程的 ...

  3. gzip解压文件报错

    #tar -xvf jdk-8u131-linux-x64.tar.gz,执行命令后报错如下: gzip: stdin: not in gzip format tar: Child returned ...

  4. iOS调用系统发送短信和邮件分享

    //发送邮件 -(void)sendMail:(NSString*)subject content:(NSString*)content{ MFMailComposeViewController*co ...

  5. 基本排序算法(Java)

    基本排序算法 (Java) 经过几次笔试,发现自己的Java基础有些薄弱,基本的排序算法掌握的还不够熟练,需要多加学习总结. 1. 选择排序 思想: 给定一个整数数组,例 int[] a ={38,6 ...

  6. PHP序列号生成函数和字符串替换函数代码

    /** * 序列号生成器 */ function snMaker($pre = '') { $date = date('Ymd'); $rand = rand(1000000,9999999); $t ...

  7. Docker安装ngnix使用ping报错

    最近在学习docker时,由于docker维护的dockerHub远程仓库的镜像文件比普通的文件小得多,所以经常碰到的情况是,一般常用的命令,会出现no command的情况.今天安装ping的时候就 ...

  8. node06

    1.数据库: server端:数据存在 client端:管理工具,node mysql内有两个单位: 库:类似文件夹,容纳表 表:存储数据 行:一条数据 列(字段,域):一个数据项 主键:数据的唯一标 ...

  9. laravel5单元测试

    https://www.cnblogs.com/love-snow/articles/7641198.html

  10. vue单页面应用刷新网页后vuex的state数据丢失的解决方案

    1. 产生原因其实很简单,因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值. 2. 解决思路一种是state里的数据全部是通过请求 ...