java web配置json_Java Web:JSON 作为配置文件,简单读写的方法

本方法依赖于 JRE 自带的 JavaScript 引擎 Rhino,无须其他第三方 JAR 包。更多这方面的资料,参见《学习使用 Java 自带的 JS 引擎》和《使用自带的 Rhino 作为 Java 的 JSON 解析包》。

读取配置文件

先大概说一说思路。首先配置文件以 *.json 格式保存在服务端磁盘上。要读取改配置文件的话,通过 java.io.File 包读取磁盘内容,然后形成接口,作为响应内容返回到客户。既然 Web 浏览器天然支持 JSON,这读取一过程我们借助 即可。得到 JSON 数据后,再通过 JavaScript 绑定到 HTML 表单上。

读取 JSON 文件内容很简单,我的代码如下:

String filePath = new RequestHelper(request).Mappath("/META-INF/site_config.js");

out.println(Fso.readFile(filePath));

RequestHelper.Mappath 和 Fso.readFile 都是我封装的函数,分别是把虚拟的相对路径还原为磁盘的绝对路径;Fso.readFile 顾名思义是读取文件内容。你可以将此写成 JSP 或 Servlet,让浏览器通过 访问得到即可。另外这里我还加入了格式化函数(Formatter),让输出的 JSON 带有缩进,更方便调试和阅读。

如上例,我是设置当前 JSP 得到 JSON 内容的,效果如下图。

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

注意我们把 JSON 显示到表单是通过下面简单的函数的:

// 数据绑定

// v1.00

function databing(data){

for(var i in data){

var el = document.querySelector('*[name="bf_Config.site.{0}"]'.format(i));

el.value = data[i];

}

}

databing(bf_Config.site);这里表单各个输入控件的 name 属性是有讲究的,命名方式都是以 JSON 的中 JSON Path 完整路径为依据,如这里的 bf_Config.site.{0}。一个控件项对应一个 JSON 节点。

表单代码如下:

网站标题前缀

placeholder="请输入旧密码" errmsg="旧密码为必填项" requiredfield />

搜索关键字

*

网站描述

*

底部版权
声明文字

*

保存

生成表单界面如下:

0818b9ca8b590ca3270a3433284dd417.png

其中要注意两处隐藏域:

一个说明是哪个 JSON 文件要被保存的,一个是 JSON 的顶级节点名。

保存配置内容

点击“保存”按钮之后,表单提交如下数据到后台。

0818b9ca8b590ca3270a3433284dd417.png

保存配置文件,一个是修改当前内存的配置信息,其次是将配置内存保存在服务端的磁盘上,所以说这里是两个主要的操作,因此也需要两个 JavaScript 运行时。一个是 BaseApplication.jsRuntime 静态类型的,常驻内存的,另外一个是用于当前请求的实例化的这么一个 JS 运行时,用于得到 JSON 序列化后的字符串。它们分别作用各不同。

以上逻辑都安排在 save(HttpServletRequest request) 方法:

private void save(HttpServletRequest request) throws Exception {

Map hash = RequestSender.getClient_Data(request);

String jsonFileFullPath = load(request, hash);

// 可以json.str() 的 变量名

String topVarName = hash.get("topVarName");

Util.isEmptyString(topVarName, "没有 topVarName 参数!");

hash.remove("topVarName");

saveRAM(hash);

String JSON_as_String = null;

try {

JSON_as_String = (String)eval("JSON.stringify(" + topVarName + ");");

} catch (ScriptException e) {

e.printStackTrace();

throw new Exception("更新配置失败,不能序列化配置!");

}

if(JSON_as_String != null){ // 持久化配置文件

String fileBody = topVarName + " = " + JSON_as_String + ";";

//System.out.println(fileBody);

//System.out.println("::::::::::::::::::2:"+jsonFileFullPath);

try {

Fso.writeFile(jsonFileFullPath, fileBody);

} catch (IOException e) {

e.printStackTrace();

throw new Exception("更新配置失败,不能保存配置!");

}

}

}

首先,我们需要把这些数据变为一个 Map:Map hash = RequestSender.getClient_Data(request);,加载到内存中,然后对其修改(实际是覆盖过程,同时对两个 js runtime 皆有效),最后保存到文件中(Fso.write)。

/**

* 写入内存,覆盖

* @param hash

*/

private void save(Map hash){

String jsCode = "";

for(String key : hash.keySet()){

jsCode = key + " = '" + hash.get(key) + "';"; // 全部保存为 String。TODO 支持其他类型

//System.out.println(jsCode);

try{

js.eval(jsCode); // 两个 js runtime

eval(jsCode);

}catch(ScriptException e) {

System.err.println("写入内存,覆盖失败!");

e.printStackTrace();

}

}

}

最后保存完毕,输出 JSON 结果:new ResponseHelper(response).outputJSON(request); 提示用户成功。应该说整个过程并不复杂,操作也足够直观。如果要说有什么地方没考虑到的,就是安全性了。实际使用中还需要注意权限,因为这是直接对服务端的文件进行写操作!

另外有一点可以优化的地方,那就是合并两个 js runtime 为一个,不知是否可行呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值