网站开发需要自己写代码吗,12306网站多少钱做的,网站域名过期怎么办,wordpress手册 chm文章目录一、安装LUA1#xff09;简单使用二、lua语法简介1、注释1#xff09;单行注释2#xff09;多行注释2、关键字3、变量1#xff09;全局变量2#xff09;局部变量4、数据类型1#xff09;Lua数组2#xff09;字符串操作5、if-else6、循环1#xff09;for循环1简单使用二、lua语法简介1、注释1单行注释2多行注释2、关键字3、变量1全局变量2局部变量4、数据类型1Lua数组2字符串操作5、if-else6、循环1for循环1 数组for循环2 泛型for循环2while循环3break提前退出循环7、函数三、Java中执行Lua脚本1、字符串方式2、文件方式3、Luaj概述1线程安全问题2性能问题四、Redis LuaEVAL命令1、EVAL命令使用示例五、总结一、安装LUA
Mac上安装LUA很简单直接使用brew相关命令
brew install lua使用lua -v命令可以看到lua已经安装完毕。
1简单使用
创建一个test.lua文件内容为
执行命令
lua test.lua输出为 二、lua语法简介
Lua 提供了交互式编程和脚本式编程
交互式编程直接在命令行中输入语法可以立即执行并查看到执行效果。脚本是编程编写脚本文件然后再执行。
官方文档http://www.lua.org/manual/5.4/
1、注释
lua提供两种注释方式单行注释和多行注释
1单行注释
使用两个减号 --2多行注释
--[[多行注释多行注释--]]2、关键字
下列为 Lua 的保留关键字和Java一样 保留关键字不能作为常量或变量。 3、变量
默认的情况下定义一个变量都是全局变量如果要用局部变量 需要声明为local
1全局变量
全局变量不需要声明给一个变量赋值后便创建了这个全局变量
访问一个没有初始化的全局变量也不会出错只不过会得到结果nil 想删除一个全局变量只需要将变量赋值为nil换言之当且仅当一个变量不等于nil时这个变量存在。 此外一般以下划线开头连接一串大写字母的名字比如 _VERSION被保留用于 Lua 内部全局变量。
2局部变量
-- 局部变量赋值
local b2 4、数据类型
Lua 是一个动态类型语言变量不要类型定义只需要为变量赋值。 值可以存储在变量中作为参数传递或结果返回。
Lua 中有 8 个基本类型分别为nil、boolean、number、string、userdata、function、thread 和 table。 1Lua数组
在Lua 数组中索引值是从 1 开始可以指定为从 0 开始。 2字符串操作
.. 连接两个字符串string.sub() 用于截取字符串string.sub(s, i [, j])s要截取的字符串i截取开始位置j截取结束位置默认为 -1最后一个字符 string.find() 用于字符串查找string.find (str, substr, [init, [plain]])在一个指定的目标字符串 str 中搜索指定的内容 substr如果找到了一个匹配的子串就会返回这个子串的起始索引和结束索引不存在则返回 nil。init 指定了搜索的起始位置默认为 1可以一个负数表示从后往前数的字符个数。plain 表示是否使用简单模式默认为 falsetrue 只做简单的查找子串的操作false 表示使用正则模式匹配。
5、if-else
条件表达式结果可以是任何值Lua认为false和nil为假true和非nil为真。
整体的if-else结构和我们使用的高级语言Java、GO类似区别在于LUA中的if()表达式满足之后想要做一些其余逻辑需要紧跟then并且流程控制以end结尾。
if(xxx) thenprint(xxx)
else if(xx) thenprint(xx)
elseprint(x)
end6、循环
1for循环
Lua 编程语言中 for语句有两大类数组for循环、泛型for循环
1 数组for循环
语法格式
for varexp1,exp2,exp3 do 执行体
end var 从 exp1 变化到 exp2每次变化以 exp3 为步长递增 var并执行一次 “执行体”。exp3 是可选的如果不指定默认为1。 2 泛型for循环
通过一个迭代器函数来遍历所有值类似 java 中的 foreach 语句
语法格式
--打印数组a的所有值
a {one, two, three}
for i, v in ipairs(a) doprint(i, v)
end i 是数组索引值v 是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数用来迭代数组。 2while循环
while 循环语句在判断条件为 true 时会重复执行循环体语句。
语法格式
while(condition)
dostatements
endstatements(循环体语句) 可以是一条或多条语句condition(条件) 可以是任意表达式在 condition(条件) 为 true 时执行循环体语句。 3break提前退出循环
和Java中的break一个作用用于退出当前循环或语句
7、函数
在Lua中函数是对语句和表达式进行抽象的主要方法。类似于Java中的方法。
Lua 函数主要有两种用途
完成指定的任务这种情况下函数作为调用语句使用计算并返回值这种情况下函数作为赋值语句的表达式使用
函数的编写方式如下
--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)if (num1 num2) thenresult num1;elseresult num2;endreturn result;
end
-- 调用函数
print(两值比较最大值为 ,max(10,4))
print(两值比较最大值为 ,max(5,6))三、Java中执行Lua脚本
Java中执行Lua脚本有两种方式字符串的方式、文件的方式
Java中想要执行LUA脚本首先需要在pom中引入相关依赖
dependencygroupIdorg.luaj/groupIdartifactIdluaj-jse/artifactIdversion3.0.1/version
/dependency1、字符串方式
对于简单的lua脚本可以直接用java字符串写
package com.saint.base.lua;import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;public class LuaString {public static void main(String[] args) {String luaStr print Saint is best man;Globals globals JsePlatform.standardGlobals();LuaValue luaValue globals.load(luaStr);luaValue.call();}
}控制台输出 2、文件方式
对于一些比较常用的、复杂的脚本可以选择存放在文件中在Java中再调用lua文件
package com.saint.base.lua;import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.jse.JsePlatform;import java.io.FileNotFoundException;public class LuaFile {public static void main(String[] args) throws FileNotFoundException {// lua脚本的文件路径String luaPath /xxxx/javaTest.lua;Globals globals JsePlatform.standardGlobals();//加载脚本文件login.lua并编译globals.loadfile(luaPath).call();LuaValue func1 globals.get(LuaValue.valueOf(print1));func1.call();LuaValue func2 globals.get(LuaValue.valueOf(print2));String luaResp func2.call(LuaValue.valueOf(saint-input-param)).toString();System.out.println(lua file return is : luaResp);}
}lua脚本文件 控制台输出 3、Luaj概述
Luaj在包装执行具体的Lua代码时, 有三种不同的模式
纯脚本解析执行(不选用任何Compiler)To Lua字节码(LuaC, lua-to-lua-bytecode compiler)默认选用To Java字节码(LuaJC, lua-to-java-bytecode compiler)
1线程安全问题
Luaj中的Globals对象不是线程安全的, 因此最佳实践是每个线程一个Globals对象。
事实上, 可以采用ThreadLocal的方式来存储该对象。
2性能问题
Lua脚本在JAVA中运行相比于直接运行Java代码会慢很多大约1000倍。
四、Redis LuaEVAL命令
在使用Redisson、JedisLua时我们可以通过redis客户端集成的、手写的LUA脚本来保证一系列命令在Redis中可以原子执行。
在redis执行lua脚本时相当于一个redis级别的锁不能执行其他操作类似于原子操作这也是redisson实现的一个关键点。
比如Redisson中的lua脚本
Redisson如何实现分布式锁可以看文章https://saint.blog.csdn.net/article/details/128176338
lua脚本中有如下几个概念 redis.call()执行redis命令。KEYS[n]指脚本中第n个参数比如KEYS[1]指脚本中的第一个参数。ARGV[n]指脚本中第n个参数的值比如ARGV[1]指脚本中的第一个参数的值。返回值中nil与false同一个意思。 1、EVAL命令
redis2.6.0版本起 采用内置的Lua解释器 通过EVAL命令去执行脚本
redis中的EVAL命令可以用于执行一段lua代码。命令格式如下 第一个参数script表示lua脚本的内容第二参数numkeys表示有多少个键值对。其余参数先把numkeys个key列出来再把numkeys个arg列出来。
Lua脚本中可以使用2个函数调用redis命令
redis.call()redis.pcall()
redis.call()与redis.pcall()相似二者唯一不同之处
如果执行的redis命令执行失败redis.call()将产生一个Lua error从而迫使EVAL命令返回一个错误给命令的调用者然而redis.pcall()将会捕捉这个错误并返回代表这个错误的Lua表。
使用示例
有那么一段逻辑
如果Redis某个key的整数值 和 某个value相等则将key对应的整数值 1000否则将key的值设置为9999
lua脚本执行命令如下
EVAL if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(INCRBY, KEYS[1], 1000); else redis.call(set, KEYS[1], 9999); return nil; end; 1 test 100根据test值的不同不同的执行结果如下 五、总结
Lua入个门知道基本的Lua脚本怎么写尤其是Redis lua的使用。
再到很多网关中都会使用一些lua脚本。