Lua开发基础
Lua是一个可扩展的轻量级脚本语言,Lua的设计目是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua的代码简洁优美,几乎在所有操作系统和平台上都可以编译和运行。
Lua脚本需要通过Lua解释器来解释执行,除了Lua官方的默认解释器外,目前使用广泛的Lua解释器叫作LuaJIT。
LuaJIT是采用C语言编写的Lua脚本解释器。LuaJIT被设计成全兼容标准Lua 5.1,因此LuaJIT代码的语法和标准Lua的语法没多大区别。LuaJIT和Lua的一个区别是,LuaJIT的运行速度比标准Lua快数十倍,可以说是一个Lua的高效率版本。
Lua模块的定义和使用
与Java类似,实际开发的Lua代码需要进行分模块开发。Lua中的一个模块对应一个Lua脚本文件。使用require指令导入Lua模块,第一次导入模块后,所有Nginx进程全局共享模块的数据和代码,每个Worker进程需要时会得到此模块的一个副本,不需要重复导入,从而提高Lua应用的性能。接下来,演示开发一个简单的Lua模块,用来存放公有的基础对象和基础函数。
//代码清单:src/luaScript/module/common/basic.lua
--定义一个应用程序公有的Lua对象app_info
local app_info = { version = "0.10" }
--增加一个path属性,保存Nginx进程所保存的Lua模块路径,包括conf文件配置的部分路径
app_info.path = package.path;
--局部函数,取得最大值
local function max(num1, num2)
if (num1 > num2) then
result = num1;
else
result = num2;
end
return result;
end
--统一的模块对象
local _Module = {
app_info = app_info;
max = max;
}
return _Module
模块内的所有对象、数据、函数都定义成局部变量或者局部函数。然后,对于需要暴露给外部的对象或者函数,作为成员属性保存到一个统一的Lua局部对象(如_Module)中,通过返回这个统一的局部对象将内部的成员对象或者方法暴露出去,从而实现Lua的模块化封装。
Lua模块的使用
接下来,创建一个Lua脚本
src/luaScript/module/demo/helloworld.lua来调用前面定义的这个基础模块src/luaScript/module/common/basic.lua文件。
helloworld.lua的代码如下:
//代码清单:src/luaScript/module/demo/helloworld.lua
---启动调试
local mobdebug = require("luaScript.initial.mobdebug");
mobdebug.start();
--导入自定义的模块
local basic = require("luaScript.module.common.basic ");
--使用模块的成员属性
ngx.say("Lua path is: " .. basic.app_info.path);
ngx.say("<br>" );
--使用模块的成员方法
ngx.say("max 1 and 11 is: ".. basic.max(1,11) );
在使用require内置函数导入Lua模块时,对于多级目录下的模块,使用require("目录1.目录2.模块名")的形式进行加载,源目录之间的“/”斜杠分隔符改成“.”点号分隔符。这一点和Java的包名的分隔符类似。
--导入自定义的模块
local basic = require("luaScript.module.common.basic");
Lua文件查找时,首先会在Nginx的当前工作目录查找,如果没有
找到,就会在Nginx的Lua包路径lua_package_path和lua_package_cpath声明的位置查找。整个Lua文件的查找过程和Java的.class文件查找的过程很类似。需要注意的是,Lua包路径需要在nginx.conf配置文件中进行配置:
lua_package_path " E:/tool/ZeroBraneStudio-1.80/lualibs/?/?.lua;;";
lua_package_cpath " E:/tool/ZeroBraneStudio-1.80/bin/clibs/?.dll;;";
这里有两个包路径配置项:lua_package_path用于配置Lua文件的包路径;lua_package_cpath用于配置C语言模块文件的包路径。在Linux系统上,C语言模块文件的类型是“.so”;在Windows平台上,C语言模块文件的类型是“.dll”。
Lua包路径如果需要配置多个路径,那么路径之间使用分号“;”分隔。末尾的两个分号“;;”表示加上Nginx默认的Lua包搜索路径,其中包含Nginx的安装目录下的lua目录。
//路径清单:一个默认的Lua文件搜索路径输出案例
./site/lualib/?.ljbc;
./site/lualib/?/init.ljbc;
./lualib/?.ljbc;
./lualib/?/init.ljbc;
./site/lualib/?.lua;
./site/lualib/?/init.lua;
./lualib/?.lua;
./lualib/?/init.lua;
.\?.lua;
E:\tool\openresty-1.13.6.2-win32\lualib\?.lua;
E:\tool\openresty-1.13.6.2-win32\lua\?.lua;
E:\tool\openresty-1.13.6.2-win32\lua\?\init.lua;;
在OpenResty的lualib下已经提供了大量第三方开发库,如CJSON、Redis客户端、MySQL客户端等,并且这些Lua模块已经包含到默认的搜索路径中。OpenResty的lualib下的模块可以直接在Lua文件中通过require方式导入:
导入
操作模块--导入redis操作模块
local redis = require("resty.redis")
--导入cjson操作模块
local cjson = require("cjson")
Lua的数据类型
Lua中大致有8种数据类型,具体如表8-1所示。
表8-1 8种数据类型
Lua是弱类型语言,和JavaScript等脚本语言类似,变量没有固定的数据类型,每个变量可以包含任意类型的值。使用内置的type(…)方法可以获取该变量的数据类型。下面是一段简单的类型输出演示程序。
--输出数据类型
local function showDataType()
local i;
basic.log("字符串的类型", type("hello world"))
basic.log("方法的类型", type(showDataType))
basic.log("true的类型", type(true))
basic.log("整数数字的类型", type(360))
basic.log("浮点数字的类型", type(360.0))
basic.log("nil值的类型", type(nil))
basic.log("未赋值变量i的类型", type(i))
end上面的方法定义在
luaScript.module.demo.dataType模块中。然后定义一个专门的调试模块runDemo,来调用上面定义的showDataType方法。runDemo.lua的代码清单如下:
---启动调试
local mobdebug = r