Heim  >  Artikel  >  Datenbank  >  So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

WBOY
WBOYnach vorne
2023-06-02 22:41:081428Durchsuche

1. LUA installieren

Es ist sehr einfach, LUA auf dem Mac zu installieren.

brew install lua
brew相关命令;

lua test.lua

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

使用lua -v命令可以看到lua已经安装完毕。

1)简单使用

创建一个test.lua文件,内容为:

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

执行命令:

--[[
 多行注释
 多行注释
 --]]

输出为:

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

二、lua语法简介

Lua 提供了交互式编程和脚本式编程:

  • 交互式编程:直接在命令行中输入语法,可以立即执行并查看到执行效果。

  • 脚本是编程:编写脚本文件,然后再执行。

1、注释

lua提供两种注释方式:单行注释和多行注释

1)单行注释

使用两个减号;

--

2)多行注释
-- 局部变量赋值
local b=2

2、关键字

下列为 Lua 的保留关键字,和Java一样 保留关键字不能作为常量或变量。

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

3、变量

默认的情况下,定义一个变量都是全局变量;如果要用局部变量 需要声明为local

1)全局变量

全局变量不需要声明,给一个变量赋值后便创建了这个全局变量;

访问一个没有初始化的全局变量也不会出错,只不过会得到结果:nil

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

只要将变量赋值为nil,就可以删除全局变量;换句话说,当且仅当变量为nil时,该变量不存在。

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

此外,一般以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。

2)局部变量
string.sub(s, i [, j])

4、数据类型

Lua 是一个动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

1)Lua数组

在Lua 数组中,索引值是从 1 开始,可以指定为从 0 开始。

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

2)字符串操作
  • .. 连接两个字符串;

  • string.sub() 用于截取字符串;

string.find (str, substr, [init, [plain]])
  • s:要截取的字符串;

  • i:截取开始位置;

  • j:截取结束位置,默认为 -1,最后一个字符;

string.find() 用于字符串查找

if(xxx) then
    print("xxx")
else if(xx) then
    print("xx")
else
   print("x")
end
  • 在一个指定的目标字符串 str 中搜索指定的内容 substr,如果找到了一个匹配的子串,就会返回这个子串的起始索引和结束索引,不存在则返回 nil。

  • init 指定了搜索的起始位置,默认为 1,可以一个负数,表示从后往前数的字符个数。

  • plain 表示是否使用简单模式,默认为 false,true 只做简单的查找子串的操作,false 表示使用正则模式匹配。

5、if-else

条件表达式结果可以是任何值,Lua认为false和nil为假,true和非nil为真。

整体的if-else结构和我们使用的高级语言(Java、GO)类似,区别在于:LUA中的if()表达式满足之后想要做一些其余逻辑,需要紧跟then,并且流程控制以end So verwenden Sie Lua-Skript in Java Ecology/Redis

# 🎜🎜#Mit dem Befehl lua -v können Sie sehen, dass Lua installiert wurde.

1) Verwenden Sie einfach
, um eine test.lua-Datei mit dem Inhalt zu erstellen:

So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

Befehl ausführen: # 🎜🎜 #

for var=exp1,exp2,exp3 do  
    <执行体>  
end

Die Ausgabe ist:

So verwenden Sie Lua-Skript im Java-Ökosystem/RedisSo verwenden Sie Lua-Skript im Java-Ökosystem/Redis

2. Einführung in die Lua-Syntax#🎜🎜##🎜🎜#Lua Bietet interaktive Programmierung und Skriptprogrammierung: #🎜🎜#
  • #🎜🎜#Interaktive Programmierung: Geben Sie die Syntax direkt in die Befehlszeile ein, Sie können sie sofort ausführen und sehen Ausführungseffekt. #🎜🎜#
  • #🎜🎜#Scripting ist Programmieren: Schreiben Sie eine Skriptdatei und führen Sie sie dann aus. #🎜🎜#
#🎜🎜#1. Kommentar #🎜🎜##🎜🎜#lua bietet zwei Kommentarmethoden: einzeilige Kommentare und mehrzeilige Kommentare #🎜🎜##🎜🎜# 1) Einzeilige Kommentare #🎜🎜##🎜🎜# verwenden zwei Minuszeichen; #🎜🎜##🎜🎜#--#🎜🎜##🎜🎜#2) Mehrzeilige Kommentare #🎜🎜#
--打印数组a的所有值  
a = {"one", "two", "three"}
for i, v in ipairs(a) do
    print(i, v)
end
#🎜🎜#2. Schlüsselwörter#🎜🎜##🎜🎜#Die folgenden Schlüsselwörter sind für Lua reserviert und können nicht als Konstanten oder Variablen verwendet werden. #🎜🎜##🎜🎜#So verwenden Sie Lua-Skript in Java Ecology/Redis #🎜🎜##🎜🎜#3. Variable #🎜🎜##🎜🎜#Standardmäßig sind alle definierten Variablen globale Variablen; wenn Sie lokale Variablen verwenden möchten, müssen diese als local deklariert werden ; #🎜🎜##🎜🎜#1) Globale Variablen #🎜🎜##🎜🎜#Globale Variablen müssen nicht deklariert werden, nachdem einer Variablen ein Wert zugewiesen wurde ##🎜🎜#Zugriff auf eine Variable ohne Beim Initialisieren globaler Variablen tritt kein Fehler auf, aber das Ergebnis ist: Null#🎜🎜##🎜🎜#So verwenden Sie Lua-Skript im Java-Ökosystem/Redis#🎜🎜##🎜🎜#Solange die Variable Null zugewiesen ist, ist die globale Variable kann gelöscht werden; mit anderen Worten, genau dann, wenn die Variable nil ist, existiert die Variable nicht. #🎜🎜##🎜🎜#So verwenden Sie Lua-Skript in Java Ecology/Redis #🎜🎜##🎜🎜##🎜🎜#Darüber hinaus sind Namen, die im Allgemeinen mit einem Unterstrich gefolgt von einer Zeichenfolge aus Großbuchstaben beginnen (z. B. _VERSION), für interne globale Variablen von Lua reserviert. #🎜🎜##🎜🎜##🎜🎜#2) Lokale Variablen#🎜🎜#
while(condition)
do
   statements
end
#🎜🎜#4. Datentyp#🎜🎜##🎜🎜#Variablen benötigen keine Typdefinitionen , muss der Variablen nur ein Wert zugewiesen werden. Werte können in Variablen gespeichert, als Argumente übergeben oder als Ergebnisse zurückgegeben werden. #🎜🎜##🎜🎜#Es gibt 8 Grundtypen in Lua: Null, Boolescher Wert, Zahl, Zeichenfolge, Benutzerdaten, Funktion, Thread und Tabelle. #🎜🎜##🎜🎜#So verwenden Sie Lua-Skript in Java Ecology/Redis #🎜🎜##🎜🎜#1) Lua-Array#🎜🎜##🎜🎜#Im Lua-Array beginnt der Indexwert bei 1 und kann so angegeben werden, dass er bei 0 beginnt. #🎜🎜##🎜🎜#So verwenden Sie Lua-Skript in Java Ecology/Redis #🎜🎜##🎜🎜#2) String-Operation #🎜🎜#
  • #🎜🎜#.. Zwei Strings verbinden ; #🎜🎜#
  • #🎜🎜#string.sub() wird zum Abfangen von Zeichenfolgen verwendet; #🎜🎜#
--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)
   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end
   return result; 
end
-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))
  • #🎜🎜#s: Die abzufangende Zeichenfolge; #🎜🎜#
  • #🎜🎜#i: Die Startposition des Abfangens; #
  • #🎜🎜#j: Abfangen der Endposition, der Standardwert ist -1, das letzte Zeichen; find( ) Wird für die String-Suche verwendet #🎜🎜#
    <dependency>
        <groupId>org.luaj</groupId>
        <artifactId>luaj-jse</artifactId>
        <version>3.0.1</version>
    </dependency>
    • #🎜🎜#Suche nach dem angegebenen Inhalts-Substr in einem angegebenen Ziel-String str, wenn If Wenn ein passender Teilstring gefunden wird, werden der Startindex und der Endindex des Teilstrings zurückgegeben. Wenn dieser nicht vorhanden ist, wird Null zurückgegeben. #🎜🎜#
    • #🎜🎜#init gibt die Startposition der Suche an, der Standardwert ist 1, es kann eine negative Zahl sein, die die Anzahl der Zeichen von hinten angibt nach vorne. #🎜🎜#
    • #🎜🎜#plain Gibt an, ob der einfache Modus verwendet werden soll. Der Standardwert ist „false“, „true“ führt nur eine einfache Suche nach Teilzeichenfolgen durch, „false“ gibt an, dass ein regulärer Mustervergleich verwendet wird . #🎜🎜#
    #🎜🎜#5, if-else#🎜🎜##🎜🎜#Das Ergebnis des bedingten Ausdrucks kann jeder Wert sein, den Lua für falsch und null hält und Nicht-Null ist wahr. #🎜🎜##🎜🎜#Die gesamte if-else-Struktur ähnelt der von uns verwendeten Hochsprache (Java, GO). Der Unterschied besteht darin, dass Sie nach dem if()-Ausdruck in LUA eine andere Logik ausführen möchten Wenn Sie zufrieden sind, müssen Sie then genau befolgen, und die Flusskontrolle endet mit end. #🎜🎜#
    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 &#39;Saint is best man&#39;";
            Globals globals = JsePlatform.standardGlobals();
            LuaValue luaValue = globals.load(luaStr);
            luaValue.call();
        }
    }
    #🎜🎜#6, Schleife#🎜🎜##🎜🎜#1) for-Schleife#🎜🎜##🎜🎜#Lua Es gibt zwei Hauptkategorien von for-Anweisungen in der Programmiersprache: Array für Schleife und generisch für Schleife#🎜🎜##🎜🎜#1> Array für Schleife#🎜🎜##🎜🎜##🎜🎜# Syntaxformat: #🎜🎜##🎜🎜#
    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);
        }
    }
    #🎜🎜#var ändert sich von exp1 zu exp2 , jede Diese Änderung erhöht var um exp3 und führt den „Ausführungskörper“ einmal aus. exp3 ist optional und hat den Standardwert 1, wenn nicht angegeben. #🎜🎜##🎜🎜##🎜🎜##🎜🎜#

    2> 泛型for循环

    通过一个迭代器函数来遍历所有值,类似 java 中的 foreach 语句;

    语法格式:

    --打印数组a的所有值  
    a = {"one", "two", "three"}
    for i, v in ipairs(a) do
        print(i, v)
    end
    • i 是数组索引值,v 是对应索引的数组元素值。

    • ipairs是Lua提供的一个迭代器函数,用来迭代数组。

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    2)while循环

    while 循环语句在判断条件为 true 时会重复执行循环体语句。

    语法格式:

    while(condition)
    do
       statements
    end
    • statements(循环体语句) 可以是一条或多条语句,condition(条件) 可以是任意表达式;

    • 在 condition(条件) 为 true 时执行循环体语句。

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    3)break提前退出循环

    和Java中的break一个作用,用于退出当前循环或语句;

    7、函数

    在Lua中,函数是对语句和表达式进行抽象的主要方法。类似于Java中的方法。

    Lua 函数主要有两种用途:

    • 完成指定的任务,这种情况下函数作为调用语句使用;

    • 计算并返回值,这种情况下函数作为赋值语句的表达式使用;

    函数的编写方式如下:

    --[[ 函数返回两个值的最大值 --]]
    function max(num1, num2)
       if (num1 > num2) then
          result = num1;
       else
          result = num2;
       end
       return result; 
    end
    -- 调用函数
    print("两值比较最大值为 ",max(10,4))
    print("两值比较最大值为 ",max(5,6))

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    三、Java中执行Lua脚本

    Java中执行Lua脚本有两种方式:字符串的方式、文件的方式;

    Java中想要执行LUA脚本,首先需要在pom中引入相关依赖:

    <dependency>
        <groupId>org.luaj</groupId>
        <artifactId>luaj-jse</artifactId>
        <version>3.0.1</version>
    </dependency>

    1、字符串方式

    对于简单的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 &#39;Saint is best man&#39;";
            Globals globals = JsePlatform.standardGlobals();
            LuaValue luaValue = globals.load(luaStr);
            luaValue.call();
        }
    }

    控制台输出:

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    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脚本文件:

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    控制台输出:

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    3、Luaj概述

    Luaj在包装执行具体的Lua代码时, 有三种不同的模式;

    • 纯脚本解析执行(不选用任何Compiler)

    • To Lua字节码(LuaC, lua-to-lua-bytecode compiler)(默认选用)

    • To Java字节码(LuaJC, lua-to-java-bytecode compiler)

    Luaj中的Globals对象不是线程安全的, 因此最佳实践是每个线程一个Globals对象。

    事实上, 可以采用ThreadLocal的方式来存储该对象。

    2)性能问题

    Lua脚本在JAVA中运行,相比于直接运行Java代码会慢很多,大约1000倍。

    四、Redis + Lua(EVAL命令)

    在使用Redisson、Jedis+Lua时,我们可以通过redis客户端集成的、手写的LUA脚本来保证一系列命令在Redis中可以"原子执行"。

    在redis执行lua脚本时,相当于一个redis级别的锁,不能执行其他操作,类似于原子操作,这也是redisson实现的一个关键点。

    比如Redisson中的lua脚本:

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    Redisson如何实现分布式锁,可以看文章:https://www.yisu.com/article/277312.htm

    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代码。命令格式如下:

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

    • 第一个参数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(&#39;get&#39;, KEYS[1]) == ARGV[1] then return redis.call(&#39;INCRBY&#39;, KEYS[1], 1000); else redis.call(&#39;set&#39;, KEYS[1], 9999); return nil; end;" 1 test 100

    根据test值的不同,不同的执行结果如下:

    So verwenden Sie Lua-Skript im Java-Ökosystem/Redis

  • Das obige ist der detaillierte Inhalt vonSo verwenden Sie Lua-Skript im Java-Ökosystem/Redis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen