代码先锋网 代码片段及技术文章聚合

Lua从基础到实战

技术标签: 案例  lua  开发语言  java

一、简介

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代表 未得到锁
版权声明:本文为weixin_54721305原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_54721305/article/details/125648123

智能推荐

Python从入门到项目实战笔记(1)基础环境

Python从入门到项目实战笔记(1)基础环境 基于明日科技出版 Python从入门到项目实战(全彩版) Python简介 Python是一种跨平台的、开源的、免费的、解释型的高级编程语言。它具有丰富和强大的库,能够吧用其他语言制作的各种模块(尤其是C/C++)很轻松地连结在一起,所以Python常被称为“胶水”语言。Python的应用领域也非常的广泛,在Web编程、图形处...

《Tensorflow 从基础到实战》00 张量,会话,变量,矩阵

《Tensorflow 从基础到实战》00 常量,会话,变量,矩阵 1.张量 1.1 固定张量 1.2 相似的张量 1.3 序列的张量 1.4 随机的张量 1.4.1真随机 1.4.2 正态分布随机张量 1.4.3 生成指定区间的随机张量 1.4.4 随机打乱 1.4.5 随机切片获取部分张量 2. 会话 2.1 会话的上下文管理器 2.2 tf.eval(),tf.InteractiveSess...

docker从入门到实战

docker 简述 Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。 开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。 Docker通常用于如下场景: web应用的自动化打包和发布; 自动化测试和持续集成、发布; 在服务型环境中部署和调整数据库或其他...

JMockit从入门到实战

目录 JMockit简介 作用 注解介绍 @Mocked @Injectable @Tested JMockit实战 测试目标 测试类 测试目标方法 设置方法 声明:该文档参考资料JMockit中文网 JMockit简介 Mock工具的一种(关于Mock思想的介绍) (点击此处,了解为什么使用JMockit) 作用 为了方便实现Mock 注解介绍 @Mocked @Injectable @Test...

GraphQL从入门到实战

前言 本来这篇文章准备51假期期间就发出来的,但是因为自己的笔记本电脑出了一点问题,所以拖到了现在😂。为了大家更好的学习GraphQL,我写一个前后端的GraphQL的Demo,包含了登陆,增加数据,获取数据一些常见的操作。前端使用了Vue和TypeScript,后端使用的是Koa和GraphQL。 这个是预览的地址: GraphQLDeom 默认用户root,密码root 这个是源码的地址: ...

猜你喜欢

quartz从入门到实战

简介:Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本可以去官网查看。 1.入门案例 1.1引入jar包   1.2创建任务类 1...

Nginx从入门到实战

0 概述 最近在进行项目开发,用到了Nginx做代理,访问前端静态资源,以前也只是听过,没有系统的学习,最近有时间进行了学习,做了一些简单的总结,以及学习案例。 1 Nginx 简介 1 什么是Nignx Nginx是一个高性能的Http和反向代理服务器,特点是占用内存少,并发性能力强,专门为性能优化而开发,经受高负载的考验。 2 反向代理 Nginx不仅可以做反向代理,实现负载均衡,还能做正向代...

SpringBoot从入门到实战

SpringBoot框架初相识 SpringBoot框架简介 SpringBoot是Spring家族中一个全新的框架,用来简化Spring应用程序的创建和开发过程,SpringBoot能简化我们之前采用的Spring MVC+Spring+MyBatis框架进行开发的过程 以往我们采用Spring MVC+Spring+MyBatis框架进行开发的时候,搭建和整合三大框架,需要做很多工作,比如配置...

Flutter 从入门到实战

本文由玉刚说写作平台提供写作赞助 版权归玉刚说微信公众号所有 原作者:杨哲丶 版权声明:未经玉刚说许可,不得以任何形式转载 前言 2018年2月27日,在2018世界移动大会上,Google发布了Flutter的第一个Beta版本。Flutter是Google用以帮助开发者在 Android/IOS 两个平台开发高质量原生应用的全新移动UI框架。 热重载(Hot Reload),作为一个安卓开发者...

aot从入门到实战

aot介绍 aot是Ahead-Of-Time的缩写,以前大家都知道java的一个定位就是半编译,半解释型语言。他把java文件编译成class文件,最后jvm解释执行class文件,jvm可以把class文件解释为对应的机器码,这个就是靠的jit。aot则是直接把class文件编译系统的库文件,不在依靠jit去做这个事情。 第一个aot的程序 demo环境 要求 版本 系统 macos java...