文档章节

「造个轮子」——cicada 设计一个配置模块

crossoverJie
 crossoverJie
发布于 2018/09/14 08:55
字数 1694
阅读 32
收藏 0

前言

在前两次的 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 之类的,请持续关注。

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

© 著作权归作者所有

crossoverJie

crossoverJie

粉丝 750
博文 101
码字总数 196561
作品 0
江北
后端工程师
私信 提问
「造个轮子」——cicada 设计一个配置模块

前言 在前两次的 cicada 版本中其实还不支持读取配置文件,比如对端口、路由的配置。 因此我按照自己的想法创建了一个 issue ,也收集到了一些很不错的建议。 最终其实还是按照我之前的想法来...

crossoverJie
2018/09/14
0
0
「造个轮子」——cicada(轻量级 WEB 框架)

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

crossoverJie
2018/09/03
0
0
「造个轮子」——设计 HTTP 请求全局上下文

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

crossoverJie
2018/10/09
42
0
「造个轮子」——cicada 源码分析

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

crossoverJie
2018/09/05
0
0
「造个轮子」——cicada(轻量级 WEB 框架)

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

crossoverJie
2018/09/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Archiva 不小心删掉了管理员权限怎么办

Archiva 的界面和 UI 比较容易出问题。 在添加用户和为用户进行权限修改的时候,不小心连 admin 这个用户的权限都删掉了。 这个时候应该如何恢复 admin 这个用户的权限? 这个时候你可以尝试...

honeymoose
44分钟前
5
0
Java8新特性之空指针异常的克星Optional类

Java8新特性系列我们已经介绍了Stream、Lambda表达式、DateTime日期时间处理,最后以“NullPointerException” 的克星Optional类的讲解来收尾。 背景 作为开发人员每天与NullPointerExceptio...

程序新视界
56分钟前
4
0
OSChina 周四乱弹 —— 福布斯终身秃头奖

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享如是我闻的单曲《地藏经上卷》: 如是我闻#今日歌曲推荐# 《地藏经上卷》- 如是我闻 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
59分钟前
243
8
Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
6
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部