mongodb + helma 实现web快速开发

MongoDB  /  houtizong 发布于 3年前   226

     Mongodb是一个高性能,开源,无模式的文档型数据库,在网上的介绍已经有很多,就不多说了。官方网址:http://www.mongodb.org/display/DOCS/Home。在某些对事务处理的要求不严格的项目中,可以考虑用它替代关系型数据库,好处是能够解决甚至是大型关系数据库都难以解决的性能问题。当然,也不是所有项目都适合。
      Helma是一个用来开发快速,稳定Web应用程序的开源框架。它使用JavaScript 来作为服务端脚本环境,从而可以除去编译周期。官方网址:http://helma.org/。
      那么这两者为什么要结合到一起呢?在学习Mongodb的实践中,我发现虽然现在的java框架有很多种,但是大都和关系型数据库联系紧密,针对nosql数据库的没有(很大可能是我没找到,毕竟java框架太多了)。Mongodb的特点是用二进制的JSON存储数据,在使用方式上有明显的脚本语言的特点,他的控制台管理工具,就是利用javascript语言进行管理。而Helma使用的也是javascript,这就是共同点。
      Helma以前我也曾经关注过,印象很深刻,他轻量,快速,稳定,独立性强。有着完美的拿来主义--可以及其简便的使用任何java类扩充功能,这就使他无所不能,这一点对我来说及其看重,我不想因为用上了某种框架,当用户要增加某项功能时,急得抓耳挠腮。当然,也有不好的,他内置一个XML数据库,通过配置文件可以实现ORM的映射。但是XML数据库的功能很弱,不堪大用。当然也可以使用任何一个支持jdbc连接的数据库,但是他的ORM映射又很简陋,远不如ruby on rails的灵活,处理多表关联很麻烦。你还可以直接使用SQL,抛弃ORM。但是经过jdbc封装的面向对象的方式和javascript写在一起总觉得别扭。
      现在,和mongodb做搭档情况就不同了,劣势转化成优势,java的强大,脚本语言的灵活可以完美结合,同时还不用担心部署的问题和运行效率,这是我迄今遇到的最好的一个解决方案。下面就以一个小例子进一步说明。这是一个简单的电话号码本的增删查改。

    首先是Global下的一个init.js,这里主要定义操作Mongodb的方法。

 

// mongodb functionalfunction getDb() {  var conn = new com.mongodb.Mongo("localhost", 27017);  var db = conn.getDB("test");  return db;}function getCollection(table) {  return getDb().getCollection(table);}function getDBObject() {  return new com.mongodb.BasicDBObject();}function getDBObjectInit(key, val) {  return new com.mongodb.BasicDBObject(key, val);}function getObjectId(id) {  return new com.mongodb.ObjectId(id);}function jsonToDBObject(jsonData) {  return com.mongodb.util.JSON.parse(jsonData);}function trim(source) {  if (source == null) return '';  return source.replace(/^\s+|\s+$/g, "")}

 从这些函数,我们不难看出在Helma中使用java类是多么的简单,甚至比在java中使用他们还要简单。

 下面是first.hac,增删查改的逻辑都在其中。

 

var coll = getCollection('name_tel');// addvar add_name = trim(req.data.add_name);var add_tel = trim(req.data.add_tel);if (add_name != '') {  var addName = getDBObject();  addName.put('name', add_name);  addName.put('telephon', add_tel);  coll.insert(addName);}// deleteif (req.data.id != null) {  coll.remove(getDBObjectInit('_id', getObjectId(req.data.id)));}// updateif (req.data.upd_id != null) {  var updName = coll.findOne(getDBObjectInit('_id', getObjectId(req.data.upd_id)));  updName.put('telephon', trim(req.data.upd_tel))  coll.save(updName);}// selectvar curSelect = coll.find();res.data.trRow = '';while(curSelect.hasNext()){  var cur = curSelect.next();  res.data.trRow += '\    <tr>\      <td>' + cur.get('name') + '</td>\      <td>' + cur.get('telephon') + '</td>\      <td><a href="second?id=' + cur.get('_id') + '">修改</a></td>\      <td><a href="first?id=' + cur.get('_id') + '">删除</a></td>\    </tr>';}res.data.pushDate = new Date();res.data.body = this.renderSkinAsString('first');this.renderSkin('page');

  下面是page.skin,可以在其中设置共同的外观,菜单之类的东西。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN"><head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>  <title>my test</title></head><body>  <div>    <img src="/static/helmaheader.png"/>  </div>  <% response.body %></body></html>

  下面是first.skin,画面中的主要内容

 

<script type="text/javascript">  function trim(source) {    return source.replace(/^\s+|\s+$/g, "")  }    function addItem() {    var form = document.form1;    if (trim(form.add_name.value) == '') {      alert('姓名得有');      return;    }    form.action = 'first';    form.submit();  }  </script><form name='form1' method="post">  <p><% response.pushDate %></p>  <table>    <tr>      <th>姓名</th>      <th>电话</th>      <th></th>      <th></th>    </tr>    <% response.trRow %>  </table>  <hr/>  <span>姓名:</span>  <input type="text" name="add_name">  <span>电话:</span>  <input type="text" name="add_tel">  <input type="button" value='添加' onClick="addItem();"></form>

  下面是second.hac要跳转到的更新画面的逻辑

 

var coll = getCollection('name_tel');var select_name = coll.findOne(getDBObjectInit('_id', getObjectId(req.data.id)));res.data.pushId = select_name.get('_id');res.data.pushName = select_name.get('name');res.data.pushTel = select_name.get('telephon');res.data.body = this.renderSkinAsString('second');this.renderSkin('page');

 下面是second.skin,更新画面中的内容。

 

<script type="text/javascript">  function updItem() {    document.form1.action = 'first';    document.form1.submit();  }</script><form name='form1' method="post">  <p>    <span>姓名:</span>    <span><% response.pushName %></span>  </p>  <p>    <span>电话:</span>    <input type="text" name="upd_tel" value='<% response.pushTel %>'>  </p>  <input type="button" value="修改" onClick="updItem();">  <a href="first">返回</a>  <input type="hidden" name="upd_id" value='<% response.pushId %>'></form>

 好了,就这么多了,是不是很简单?在这个框架下开发,几乎和在ror下开发一样的舒服。还有一点是ror所没有的,就是Helma有一个很棒的调试环境,可以单步跟踪,察看变量内容,运行代码,虽然简单,但真的很方便。

    前面说了那么多优点,局限性也要说说。

首先是来自Mongodb的,他没有事务,操作也不是原子的,在某些十分重要的场合,例如金融行业,是不能用;Mongodb太过灵活,不像SQL,如果表名,字段名不对是会报错的,在测试中很容易就会发现,Mongodb的理念是不存在,我就给你建一个,所以要格外小心,别写错了。再说说Helma,最大的遗憾我觉得是skin里接收的只能是字符串类型的数据,有些复杂的显示逻辑不得不转移到hac中生成html片断返回,虽然不影响功能,但是毕竟显示层的东西写在两个地方看起来不太舒服。其他的,虽然没有用到ORM,但我觉得不是问题,只要我喜欢这种方式。老学究可能会不高兴,但是我觉得使用框架是要给我们带来方便,而不是束缚我们的枷锁。

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客