基于 JSON 格式的通用配置中心(一)

关于应用 JSON 作为配置文件,并不鲜见。小弟若干年前亦有这方面的尝试,详见《Java Web:JSON 作为配置文件,简单读写的方法》,那时不成熟的地方还很多,问题不少——这当然是今天回过头去看的。不过好在我坚持下来了,还是抱着 JSON 不放,打造今天的配置中心。

为什么要用 JSON 作配置文件使用呢?如果要简单使用一个配置文件,大多数人会立刻想到 Java 的 properties 文件,或者 win 下面的 *.ini 文件,它们都是键值对的形式来保存属性集。然而 properties 文件只支持单层结构,且类型只有字符串。于是笔者考虑另外一种格式作为配置文件,这样 JSON 作为一种通用、可扩展的文本存储结构进入了笔者思考的视野中——到底 JSON 能不能作为配置文件使用呢?通过本配置系统的尝试,应该会给大家带出答案的。

配置 JSON

所谓配置 JSON 就是普通的一个 JSON。我们约定 {} 开始,而不是数组 []

{
	"site" : {
		"titlePrefix" : "大华官网",
		"keywords" : "大华•川式料理",
		"description" : "大华•川式料理饮食有限公司于2015年成立,本公司目标致力打造中国新派川菜系列。炜爵爷川菜料理系列的精髓在于清、鲜、醇、浓、香、烫、酥、嫩,擅用麻辣。在服务出品环节上,团队以ISO9000为蓝本建立标准化餐饮体系,务求以崭新的姿态面向社会各界人仕,提供更优质的服务以及出品。炜爵爷宗旨:麻辣鲜香椒,美味有诀窍,靓油用一次,精品煮御赐。 ",
		"footCopyright":"版权所有" 
	},
	"dfd":{
		"dfd":'fdsf',
		"id": 888,
		"dfdff":{
			"dd":'fd'
		}
	},
	"clientFullName":"大华•川式料理",
	"clientShortName":"大华",
	"isDebug": true,
	"data" : {
		"newsCatalog_Id" : 6,
		"jobCatalog_Id" :7
	}
}

假设我们规定配置文件命名是 site_config.json,保存在 classpath 根目录下(一般是与 com 包同级的)。这样,通过 class.getClassLoader().getResource("").getPath() 就可以获取磁盘的绝对位置。当然,我们有相应的类封装好该逻辑,不用额外去写(当然保存位置不一样的话要另说)。这个类就是接下来要说的 ConfigService。

如何读取配置

ConfigService 负责 JSON 的序列化和反序列化工作——简单说就是读取 JSON 内容和保存 JSON,这样 JSON 才能变为 Java 可理解的对象。

读取配置之前必须将其加载,对应的方法是 ConfigService.load()/load(String jsonPath)(后者可指定配置文件路径而不是默认),不过这一般不需要我们手动调用,框架内会自动调用,具体做法是:增加一个 Web 监听器,于 ServletContextListener.contextInitialized() 内调用即可——当然这是框架封装好的,一般不需要我们关心,实际我们要懂得是怎么读取配置。这个问题我们分为 Java 中读取和表示层中读取。

Java 代码中读取配置

这个很简单,就是访问静态属性 ConfigService.config,所有的配置保存在这个 config 中。这个 config 是扩展 HashMap 的自定义对象也就是说它是一个 map。所谓读取方法就是 map.get(“XXX”) 的使用。

public class ConfigService {
	/**
	 * 所有的配置保存在这个 congfig 中
	 */
	public static Config config;
    ...
}

Config 继承自 HashMap<String, Object>。

public class Config extends HashMap<String, Object>

HashMap 中的配置值是 Object 类型,所以还不能直接使用,需要强类型转换一下。

类型转换倒不是麻烦,真正麻烦的是每访问一层对象,就要 get 一下,故所以为了读取一个配置会出现读 n 层的麻烦。有鉴于此,我们提供了方便的一个“扁平化 map”的访问机制:只要输入字符串“aa.bb.cc” 即可直接返回配置值。

public class ConfigService {
	/**
	 * 所有的配置保存在这个 congfig 中
	 */
	public static Config config;
	/**
	 * 所有的配置保存在这个 congfig 中(扁平化处理过的)
	 */
	public static Map<String, Object> flatConfig;
    ...
}

扁平化读取 ConfigService.flatConfig 即可。

指定类型读取配置

前文提到读取到的配置内容要强制转换才能使用。这样就不太方便了,对此,我们采用指定类型的方法,免去强类型转换的步骤。当然这需要程序员明确配置值的类型为何,否则会抛出类型转换的异常。

转换方法有面向 Boolean、Int、String 这三种常见的类型。

/**
 * 读取配置并转换其为特定类型。仅对扁平化后的配置有效,所以参数必须是扁平化的 aaa.bbb.ccc 格式。
 * 
 * @param key
 *            配置键值
 * @return 配置内容
 */
public static boolean getValueAsBool(String key);
public static int getValueAsInt(String key);
public static String getValueAsString(String key);

需要注意的是,这三个方法仅对扁平化后的配置有效(即访问 flatConfig),所以参数必须是扁平化的 aaa.bbb.ccc 格式。

页面模版中读取配置

怎么把配置开放给页面读取使用呢?方法多种多样~

第一种方法是保存在 Servlet 上下文。首先在初始化 Servlet 时执行 ServletContext.setAttribute(“all_config”, ConfigService.config); 所有配置保存在 all_config,读取某个配置 getAttribute(“all_config”).get("")。当然不会直接在页面写 Java 语句,而是 EL 表达式读取,那样方便得多,如 ${all_config.site.keywords}。

<head>
    <meta charset="utf-8" />
    <meta name="keywords"    content="${all_config.site.keywords}" />
    <meta name="description" content="${all_config.site.description}" />
    <meta name="author"      content="Frank Chueng, frank@ajaxjs.com" />

有时候并不具备修改 ServletContext 初始化的条件,于是我们可以考虑第二种方法,就是页面实例化 ConfigService 对象,然后 EL 表达式就可以访问配置变量了。因为在页面中,所以建议采用标签的写法实例化。

<jsp:useBean id="ConfigService" class="com.ajaxjs.config.ConfigService" scope="request" />
<%-- 读取配置 --%>
${ConfigService.config.site.keywords}

读取配置的一个例子

这里写图片描述
关于通用配置中心的说明,容我先休息下,先说到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sp42a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值