Lua从基础到实战

一、简介

1、什么是Lua

Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

Lua 是巴西里约热内卢天主教大学里的一个研究小组于 1993 年开发的。

其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

2、Lua 特性

  • 轻量级: 它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
  • 可扩展: Lua提供了非常易于使用的扩展接口和机制:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
  • 其它特性
    • 支持面向过程(procedure-oriented)编程和函数式编程(functional programming);
    • 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;
    • 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
    • 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等

3、在线调试工具

Lua在线调试工具: https://wiki.luatos.com/_static/luatos-emulator/lua.html

测试:

-- 打印内容
print('Hello,Lua!')

二、变量类型

-- 在lua中声明变量可以使用以下写法
num1 = 1;
-- 上述代码声明的是一个全局变量,可以使用 local 关键字声明一个局部变量
local num2 = 1;

1、nil

nil类型就是类似于其它语言的null类型,在Lua中没有被声明的都是nil类型

-- 未声明过a变量,打印直接是nil
print(a)

2、number

number类型是数值型 包括浮点数

-- 声明一个number类型变量
local num1 = 10

3、字符串

string类型,与java一样支持转义字符\n换行字符 \t空格

字符串是若干封装在双括号(“)或单括号(‘)内的字符。字符串示例如下:

  • “fish”
  • ‘fish’
  • “5467”
  • “a line”
-- 双引号声明
local str1 = "abcdefg"
-- 单引号声明
local str2 = 'abcdefg'
-- 多行文本声明,打印原始内容 转义字符不会被转换
local str3 = [[
	abcdefg\dasdc\dn
]]
字符串拼接
local str1 = "Hello,"
local str2 = "Lua"
print(str1..str2)
-- 输出内容Hello,Lua

注意:与Java不同的是这里的字符串拼接使用的是..而不是+

获取字符串长度
local str1 = "abcdefg"
print(#str1)	-- 输出str1字符串的长度
类型转换
-- 字符串转number
local num1 = tonumber('10')	-- 结果为数值类型10
-- number转字符串
local str1 = tostring(10)	-- 结果为字符串类型10
-- 不合法转换
local str = tonumber('abc')	-- 结果转换为nil

4、boolean

boolean类型有两种值:true和false

-- 声明一个bool类型
local flag = true

注意:在lua中不等于是用 ~=来标识 而不是用 !=

lua也支持 与或非 等操作

5、函数

类似于Java中的方法

-- 声明函数语法
function 函数名(参数)
   	-- 主体
    -- return 返回值
end   

6、table

类似于Java中的集合,与Java不同的是下标是从1开始的,而不是从0

-- 声明table
local tb = {10,"jiabin",{},function() end}
-- 打印jiabin
print(tb[2])
-- 打印不存在的下标
print(tb[8])	-- 输出结果nil

-- 赋值
tb[5] = "2022-7-6" -- 为下标5赋值
print(#tb)	-- 打印table的长度

-- 插入元素
table.insert(tb,"hahah")	--在最后一位插入元素
table.insert(tb,2,"hahah")	--在table的第2位插入元素,后面的元素会被往后挤

-- 移除元素
table.remove(tb.2)	-- 移除下标为2的元素
local abc = table.remove(tb.2)	-- 存储被移除的元素 
使用字符串为下标
local student = {
	stuId = 1,
	stuName = "jiabin",
	stuAge = "18"
}
print(student['stuName'])	-- 输出jiabin
print(student.stuName)	-- 输出jiabin

五、分支判断

注意:在Lua脚本中,0代表真

1、普通if

-- 普通判断
if 条件 then
	-- 主体
end

2、if-else

-- if else
if 条件 then
	-- 主体
else
    -- 主体
end   

3、多分支

-- 多分支
if 条件 then
	-- 主体
elseif 条件 then
    -- 主体
else
    -- 主体
end   

六、循环

1、for循环

-- for
for 变量=初始值,结束值,步长 do
	-- 主体
end

-- 循环输出10次
for i=1,10 do
	print(i)
end    

-- 倒叙排序
for i=10,1,-1 do
    print(i)
end    

2、while循环

-- while
local num = 10
while num > 1 do
	print(num)
    num = num - 1	-- Lua中不支持自减:n-=1
end

七、使用Lua操作Redis

1、分布式锁

  1. 创建maven项目导入依赖

    • <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
      </dependencies>
      
  2. 创建配置文件

    【application.properteis】

    • # 指定端口号
      server.port=8199
      
      # 连接redis
      spring.redis.host=192.168.171.138
      spring.redis.port=6379
      
  3. 创建配置类

    【LuaRedisConfig:注意正确指定lua脚本位置】

    • /**
       * @Author 嘉宾
       * @Data 2022/7/6 20:37
       * @Version 1.0
       * @Description 用于声明lua
       */
      @Configuration
      public class LuaRedisConfig {
      
          /**
           * 分布式锁脚本
           * @return
           */
          @Bean
          public DefaultRedisScript<Long> lockRedisScript() {
              // 定义DefaultRedisScript
              DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
              // 指定lua脚本路径
              redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/lock.lua")));
              // 设置返回类型
              redisScript.setResultType(Long.class);
              return redisScript;     // 返回lua脚本内容
          }
          
      }
      
  4. resources目录下创建目录script目录在其目录下创建Lua脚本文件

    • local lockUUID = KEYS[1]    -- 锁中的uuid值
      local uuid = ARGV[1]        -- 用户的uuid值
      
      -- 判断锁中的uuid是否与用户的uuid相等
      if redis.call('get',lockUUID) == uuid then
          return redis.call('del',lockUUID)   -- 相等的话就释放锁
      else    -- 未获得锁
          return 0    -- 返回0
      end
      
  5. 创建controller编写接口

    • /**
       * @Author 嘉宾
       * @Data 2022/7/6 20:39
       * @Version 1.0
       * @Description
       */
      @RestController
      @RequestMapping("/lua")
      public class TestController {
      
          @Autowired
          private StringRedisTemplate stringRedisTemplate;
      
          @Resource
          private DefaultRedisScript<Boolean> lockRedisScript;    // 分布式锁脚本
      
          /**
           * 计数
           * @return
           */
          @GetMapping("/getLock")
          public String getLock(){
              // 生成UUID
              String uuid = UUID.randomUUID().toString();
              // 1、获取锁:true得到锁,false未得到
              Boolean redisLock = stringRedisTemplate.opsForValue().setIfAbsent("lock_redis", uuid,3, TimeUnit.SECONDS);
              // 判断是否得到锁
              if(redisLock){
                  // ...自己的业务
                  String value = stringRedisTemplate.opsForValue().get("num");
                  if(StringUtils.isEmpty(value)){
                      stringRedisTemplate.opsForValue().set("num","1");
                  }
                  int num = Integer.parseInt(value + "") + 1;
                  stringRedisTemplate.opsForValue().set("num",num+"");
                  // 获取锁中的内容
                  String lockUUID = stringRedisTemplate.opsForValue().get("lock_redis");
                  // 使用Lua脚本比较
                  // 指定参数
                  List<String> keys = Arrays.asList(lockUUID);
                  stringRedisTemplate.execute(lockRedisScript,keys,uuid);
                  return "success"+num;
              }else{
      //            // 每隔0.1秒再获取一次
      //            try {
      //                Thread.sleep(100);
      //                this.getLock();
      //            }catch (InterruptedException e){
      //                e.printStackTrace();
      //            }
                  return "miss";
              }
          }
      
      }
      
  6. 测试 访问接口 localhost:8199/lua/getLock

    • 返回success:访问量代表得到锁并进行计数
    • 返回miss代表 未得到锁
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值