blog icon indicating copy to clipboard operation
blog copied to clipboard

学习alilua - 制作快餐点餐工具

Open hanxi opened this issue 10 years ago • 0 comments

一、搭建环境

参考: http://alilua.com/docs.html

下载和编译alilua

$ git clone https://github.com/oneoo/alilua.git
$ cd alilua
$ make

设定网站目录

这是调整后的目录,将alilua作为子工程放入工程目录。

project/
├── alilua/             # alilua源码目录
├── css/
├── js/
├── scripts/            # lua脚本目录
│   ├── index.lua
│   └── upload.lua
├── template/           # html模板目录
│   └── index.html
├── restart.sh          # 快速重启脚本
├── route.lua           # alilua路由脚本
├── host-route.lua      # alilua路由配置
└── uploaddir/          # 上传文件目录

快速重启脚本(方便快速调试)

  • 试过把cache关闭,但是没起到效果,所以就写了个脚本快速重启
  • 启动alilua的命令:./alilua process=4 bind=9999 daemon host-route=host-route.lua
  • 关闭alilua的函数:
stop()
{
    pid=`ps -ef| grep "alilua" | grep -v grep | awk '{print $2}' `
    if [ "$pid"x != x ]; then
        kill -9 $pid
        echo "stop alilua"
    fi
}

二、快餐点餐工具需求

  • 上传图片,支持多张
  • 显示最新的菜单图片
  • 显示点餐人名单,并载入已经点餐人的数据
  • 提交订单(菜名和价格由点餐人输入)
  • 基本的权限管理,可以防止误操作帮他人点餐或者修改别人的订单
    • 该功能留到以后完善时做

三、开始编码

index.lua和模板的使用

  • 参考:http://alilua.com/docs.html#模板引擎
  • 就一句话加载index.html:rts, err = dotemplate("/template/index.html")
  • 这里说一下文件路径问题
    • alilua中定义了一个__root变量保存主路径,而__root来源于host-rote.lua中配置host_route['*'] = '/home/hlm-devel/www/ordering/route.lua'route.lua的父目录路径。
    • core.lua中实现的函数参数涉及到文件时,都会加上__root前缀,所以在使用这些函数的时候不需要自己添加__root
  • index.html我就用到了模板中的include命令用来包含header.htmlfooter.html

使用jsonrpc实现api请求

  • 最新版本的alilua中没有了文档中所说的jsonrpc_handle函数,而且get_post_body函数的名字改成了get_request_body
  • 通过查看老版本的alilua,我找出了jsonrpc_handle函数的实现,拷贝出来修改get_post_body,在新版本中依然可以使用。
  • 参考http://alilua.com/docs.html#jsonrpc_handle实现远程RPC

jsonrpc.js的实现

  • 官网的客户端例子是使用jQuery实现的,小工具不想使用那么强大的库。
  • 网上找了一堆一些纯js的实现,在github上看到jquery-jsonrpc的实现比较简单,因此参考这个库写了个纯js版本的jsonrpc库,已经上传到github了jsonrpc.js

MySQL数据库操作的封装(alilua的require和dofile)

  • 单独建立db.lua文件封装用到的mysql操作
  • 如果直接在db.lua中执行mysqlconnect函数,不能使用require包含文件,因为

参考:https://github.com/oneoo/alilua/issues/27

因为 require 过程中产生的 Lua 运行环境不是一个协程,所以会报 attempt to yield across C-call boundary 错误。

你把 require 改为 dofile 就可以运行的。

  • 如果非要使用require,则需要在 db.lua 里面把数据库操作封装成 function ,再给调用者使用。我用的是这种方式。

文件上传的实现

  • 不想用 alilua 示例中那个 form 的例子的实现方式(标准的 html post 请求方式)
  • 我采用 AJAX 实现 post 请求传文件内容, url 参数中传文件名的方式实现。
  • AJAX 发送 post 请求遇到 sendAsBinary 函数在谷歌浏览器被移除的问题。
    • 谷歌一搜就有解答
if(!xhr.sendAsBinary){
    xhr.sendAsBinary = function(datastr) {
        function byteValue(x) {
            return x.charCodeAt(0) & 0xff;
        }
        var ords = Array.prototype.map.call(datastr, byteValue);
        var ui8a = new Uint8Array(ords);
        this.send(ui8a.buffer);
    }
}
  • post 内容全部存放文件内容,所以一次 post 只发一个文件。
  • 使用read_request_body循环读取 post 内容存入 uploaddir目录下面。

js实现下载csv数据

  • 使用 html <a 标签实现: <a href="data:text/csv;,xxxxxx"></a>
  • 遇到编码问题
    • alilua 全部使用UTF-8编码,发送到客户端的数据因此也是UTF-8的数据
    • 使用 excel 打开UTF-8格式的 csv 文件会出现中文乱码,用 notepad++ 打开不乱码
    • 在字符串前面添加 BOM 头也不管用,参考: Web 端 js 导出csv文件(使用a标签)
    • 最后改用转成 gb2312 编码(只在客户端里面转码)搞定了,参考:unicode与GB2312的相互转换(js))

添加luapath到配置文件

  • 参考 code-cache-ttl 的配置
  • host-route.lua 文件中添加luapath的配置:config['lua-path']='xxxx/?.lua;'
  • vhost.c 文件中添加全局变量lua_path:lua_path = get_string_in_table(L, "lua-path", &tl);
  • worker.c 中把 lua_path 加入到 package.path 中: sprintf(buf_4096 + epd->vhost_root_len + 1, "?.lua;%s/lua-libs/?.lua;%s", process_chdir, lua_path);
  • 重新编译就搞定,已经修改好的代码在这里hanxi/alilua

源代码在这里:https://github.com/hanxi/alilua-demo-ordering

在此感谢alilua的作者oneoo在百忙之中抽空帮助我解答疑问

hanxi avatar Mar 04 '15 09:03 hanxi