让Ioc容器帮你规划properties文件

Jul 10, 2017 10:38:44 AM

作者:zozoh

配置文件的痛苦

一个 Java 项目,无论大小,多半是有那么几个配置文件的,比如:

  • 数据库连接啦
  • 关键的文件路径啦
  • 一些曝露给运维人员的配置项啦
    如果我们采用了 Ioc 方式组织我们的程序,我们(程序员)会理直气壮的对运维人员说:“你去改xxxx Ioc 文件去。”

老实说,运维人员会恨死你,我列一个很简单的 JSON 配置文件:

  1. var ioc = {
  2. // 数据源
  3. dataSource : {
  4. type :"org.apache.commons.dbcp.BasicDataSource",
  5. events : {
  6. depose :"close"
  7. },
  8. fields : {
  9. driverClassName : "com.mysql.jdbc.Driver",
  10. url : "jdbc:mysql://127.0.0.1:3306/mydb",
  11. username : "root",
  12. password : "123456",
  13. initialSize : 10,
  14. maxActive : 100,
  15. testOnReturn : true,
  16. //validationQueryTimeout : 5,
  17. validationQuery : "select 1"
  18. }
  19. },
  20. // Dao
  21. dao : {
  22. type :'org.nutz.dao.impl.NutDao',
  23. args : [ {refer :"dataSource"}]
  24. }
  25. };

这个配置文件就是简单的配置了以下数据源,以及一个 Dao 对象。一个运维人员打开这个文件,首先映入眼帘的就是 "org.apache.commons.dbcp.BasicDataSource" 以及 depose :"close"他会吓的够呛,心里嘀咕:"这TM是神马东西!"

运维人员希望看到什么呢? 他希望看到这个:

  1. db-driver=com.mysql.jdbc.Driver
  2. db-url=jdbc:mysql://127.0.0.1:3306/mydb
  3. db-username=root
  4. db-password=123456

这样格式的文件,傻子也知道怎么维护。

当然,很多小JIAN人喜欢XML,这样的文件

  1. <db>
  2. <driver>com.mysql.jdbc.Driver</driver>
  3. <url>jdbc:mysql://127.0.0.1:3306/mydb</url>
  4. <username>root</username>
  5. <password>123456</password>
  6. </db>

TA 看到会欢喜的不得了。

总之,有没有什么办法,能够让运维人员之看到他们喜欢看到的文件,而程序员则继续维护自己的 Ioc 文件呢? 怎么把这两种文件连接起来呢?

有,实际上,从很早以前,Nutz 就很好的支持了这样的做法,不过这次,郑重写个文档出来,也是为了避免有人再有这个问题

答案是:采用 java 型注入值

用 Properties 举个例子

就用上面的例子,如果我们需要暴露给运维人员一个 properties 文件任其修改:

  1. -----------------------------------------------------[下面是 myapp.properties 文件的内容]---
  2. db-driver=com.mysql.jdbc.Driver
  3. db-url=jdbc:mysql://127.0.0.1:3306/mydb
  4. db-username=root
  5. db-password=123456

那么我们的 Ioc 文件就改成这样:

  1. var ioc = {
  2. // 读取配置文件
  3. conf : {
  4. type : "org.nutz.ioc.impl.PropertiesProxy",
  5. fields : {
  6. paths : ["myapp.properties"]
  7. //paths : ["custom/"]
  8. }
  9. },
  10. // 数据源
  11. dataSource : {
  12. type :"org.apache.commons.dbcp.BasicDataSource",
  13. events : {
  14. depose :"close"
  15. },
  16. fields : {
  17. driverClassName : {java :"$conf.get('db-driver')"},
  18. url : {java :"$conf.get('db-url')"},
  19. username : {java :"$conf.get('db-username')"},
  20. password : {java :"$conf.get('db-password')"},
  21. initialSize : 10,
  22. maxActive : 100,
  23. testOnReturn : true,
  24. //validationQueryTimeout : 5,
  25. validationQuery : "select 1"
  26. }
  27. },
  28. // Dao
  29. dao : {
  30. type :'org.nutz.dao.impl.NutDao',
  31. args : [ {refer :"dataSource"}]
  32. }
  33. };

这里有几个重点

  • Nutz 提供了一个类 org.nutz.ioc.impl.PropertiesProxy,他能读取并解析一个 properties 文件
  • 在 Ioc 容器中,我们创建一个这样的单例对象,随便起个名字,比如叫 "config"
  • 那么根据配置 "myapp.properties" 会被 PropertiesProxy 类加载
  • 通过 java 调用,你可以直接调用 "config" 对象的 get 方法
  • 这样,你就能将分散在各个 Ioc 文件中的值集中到一个 properties 文件里了

使用PropertiesProxy实现更简洁的构造方式

dao.js

  1. var ioc = {
  2. // 读取配置文件
  3. conf : {
  4. type : "org.nutz.ioc.impl.PropertiesProxy",
  5. fields : {
  6. paths : ["custom/"]
  7. }
  8. },
  9. // 数据源
  10. dataSource : {
  11. factory : "$conf#make",
  12. args : ["com.alibaba.druid.pool.DruidDataSource", "db."],
  13. type : "com.alibaba.druid.pool.DruidDataSource",
  14. events : {
  15. create : "init",
  16. depose : 'close'
  17. }
  18. },
  19. // Dao
  20. dao : {
  21. type :'org.nutz.dao.impl.NutDao',
  22. args : [ {refer :"dataSource"}]
  23. }
  24. };

custom/db.properties文件

  1. db.url=jdbc:mysql://127.0.0.1:3306/nutzbook
  2. db.username=root
  3. db.password=root
  4. db.validationQuery=select 1
  5. db.maxActive=50
  6. db.testWhileIdle=true
  7. db.filters=mergeStat
  8. db.connectionProperties=druid.stat.slowSqlMillis=2000
  9. db.defaultAutoCommit=true

重点是 factory配置, 使用$conf的make方法,可以根据一个类和指定前缀,生成一个对象

关于XML

如果你打算给你的运维人员看 XML 怎么办呢?抱歉,Nutz 木有给出内部支持,但是简单的要命,你需要:

  • 提供一个 XML 配置解析类,从xml读取内容,然后,提供 get 方法
  • 在 Ioc 配置的任何地方,你都可以用 java 调用的方式,调用 get 方法

我是用Annotation的Ioc

如果是这样,那么 @Inject 可以这样写:

  1. @Inject("java:$config.get('xxxxx')")
  2. private String myXXXX;

关于更多扩展的意淫

现在的云端应用,你不弄七八台机器放在一负载均衡后面,你都不好意思叫它们服务器。并且这些机器基本都是跑一样的程序,用一样的配置文件,很多运维人员(尤其是不会写脚本的鼠标派运维人员)会很痛苦:

“配置文件同步害死人呀!”

那么,如果你把关键的配置信息放到一张数据表里,然后自己提供一个类 …

  1. +--------+ +------------+ +----------+
  2. | Ioc | <<< {java:...} <<< | Your Class | <<<<<< | Database |
  3. +--------+ +------------+ +----------+

你只需要修改数据表,然后重启各个应用 ……

根据这个思路,你可以将你的关键配置信息汇集在:

  • 数据表里
  • YAML 或者其它什么运维人员喜欢的格式上
  • 电子表格中
    写一个解析类动态读取,于是,整个世界就会安静了 …

本页面的文字允许在知识共享 署名-相同方式共享 3.0协议GNU自由文档许可证下修改和再使用。

原文: http://nutzam.com/core/ioc/ioc_properties.html