黑马程序员Redis教程学习笔记(第2部分):Lua语法与OpenResty实践
课程概述
本篇笔记涵盖黑马程序员Redis教程中关于Lua语法基础、OpenResty安装与使用的重要章节。主要包含Lua的函数与条件控制、OpenResty的安装与配置、以及如何使用OpenResty实现多级缓存架构中的业务逻辑。
1. Lua语法进阶:函数与条件控制
函数定义
在Lua中,函数的定义语法如下:
function 函数名(参数列表)
-- 函数体
return 返回值 -- 可选
end例如,封装一个打印数组的函数:
local function print_arr(arr)
for index, value in ipairs(arr) do
print(value)
end
end
-- 使用函数
local arr = {'java', 'lua', 'python'}
print_arr(arr)条件控制
Lua中的条件控制语法与Java类似,但有一些区别:
if 条件 then
-- 条件为真时执行
elseif 其他条件 then
-- 其他条件为真时执行
else
-- 都不满足时执行
end逻辑运算符使用英文单词: - and 代表 逻辑与 - or 代表 逻辑或
- not 代表 逻辑非
特别注意:not nil 代表 true,因为nil代表false
实际应用:带条件判断的函数
local function print_table(t)
if not t then -- 如果t是nil
print("数组不能为空")
return
end
for key, value in pairs(t) do
print(key, value)
end
end2. OpenResty安装与配置
OpenResty简介
OpenResty是一个基于Nginx的高性能Web平台,为Nginx提供了大量的Lua库、语言接口和第三方模块,使其具备了编写自定义业务逻辑的能力。
安装步骤
- 安装OpenResty依赖库
- 配置OpenResty仓库地址
- 安装OpenResty及其管理插件
- 配置环境变量
安装完成后,OpenResty的主要目录结构: - /usr/local/openresty/ - 主目录 - /usr/local/openresty/nginx/ - Nginx相关文件 - /usr/local/openresty/lualib/ - Lua库文件 - /usr/local/openresty/bin/ - 可执行文件
启动与管理
- 启动:
nginx - 重新加载配置:
nginx -s reload - 停止:
nginx -s stop
配置简化
OpenResty的配置文件位于/usr/local/openresty/nginx/conf/nginx.conf,为便于开发,通常使用简化版配置,移除大量注释。
3. OpenResty快速入门:业务逻辑实现
OpenResty与Nginx的关系
- Nginx:反向代理服务器,本身不具备业务逻辑处理能力
- OpenResty:基于Nginx,增加了Lua支持,可编写业务逻辑
实现商品详情页查询
在nginx.conf中配置:
# 加载OpenResty的Lua模块 lua_package_path "/usr/local/openresty/lualib/?.lua;;"; lua_package_cpath "/usr/local/openresty/lualib/?.so;;";server { listen 8080;
# 拦截商品查询请求 location ~ /api/item/(\d+) { # 指定响应类型 default_type application/json; # 由Lua文件处理请求 content_by_lua_file lua/item.lua; }
}
在lua/item.lua中实现业务逻辑:
-- 返回假数据作为测试
ngx.say([[{
"id": 1001,
"name": "华为手机",
"price": 1999,
"image": "xxx.jpg",
"stock": 100
}]])4. OpenResty获取请求参数
五种请求参数获取方式
路径占位符参数(最复杂)
location ~ /api/item/(\d+) { # 参数会存到ngx.var[1]数组中 content_by_lua_file lua/item.lua; }在Lua中获取:
local id = ngx.var[1] -- 获取路径中的数字参数请求头参数
local headers = ngx.req.get_headers() local user_agent = headers.user_agentGET请求参数
local args = ngx.req.get_uri_args() local id = args.idPOST表单参数
ngx.req.read_body() -- 先读取请求体 local args = ngx.req.get_post_args() local username = args.usernameJSON参数
ngx.req.read_body() local data = ngx.req.get_body_data() -- 需要使用JSON解析库处理
实际应用:动态获取商品ID
-- 获取路径参数
local id = ngx.var[1]
-- 返回包含动态ID的数据
ngx.say([[{
"id": ]] .. id .. [[,
"name": "商品名称",
"price": 999
}]])5. OpenResty封装HTTP请求工具
发起HTTP请求
使用ngx.location.capture API发起内部请求:
local res = ngx.location.capture(
"/backend", -- 请求路径
{
method = ngx.HTTP_GET, -- 请求方法
args = {id = 123}, -- GET参数
body = "data" -- POST请求体
}
)
-- 获取响应
local status = res.status -- 状态码
local header = res.header -- 响应头
local body = res.body -- 响应体配置反向代理
由于capture请求会被Nginx内部捕获,需要配置反向代理:
location /item {
proxy_pass http://192.168.150.1:8081; -- Tomcat服务器地址
}这样内部请求/item会被代理到Tomcat服务器。
封装通用HTTP请求工具
创建common.lua文件:
-- 封装GET请求函数
local function read_http(path, params)
local res = ngx.location.capture(
path,
{
method = ngx.HTTP_GET,
args = params
}
)
-- 检查请求是否成功
if not res then
ngx.log(ngx.ERR, "http not found: ", path, " ", params)
ngx.exit(404)
end
return res.body
end
-- 导出函数
local _M = {
read_http = read_http
}
return _M使用通用工具
-- 导入工具模块
local common = require "common"
local read_http = common.read_http
-- 使用工具发起请求
local item_json = read_http("/item/" .. id, nil)6. OpenResty向Tomcat发送HTTP请求
完整的商品查询流程
-- 导入工具
local common = require "common"
local cjson = require "cjson"
-- 获取路径参数
local id = ngx.var[1]
-- 查询商品信息
local item_json = common.read_http("/item/" .. id, nil)
local item_data = cjson.decode(item_json) -- JSON转Lua table
-- 查询库存信息
local stock_json = common.read_http("/item/stock/" .. id, nil)
local stock_data = cjson.decode(stock_json)
-- 合并数据
item_data.stock = stock_data.stock
item_data.sold = stock_data.sold
-- 返回结果
ngx.say(cjson.encode(item_data)) -- Lua table转JSONJSON处理
使用cjson库处理JSON数据: - cjson.encode(table) - Lua table转JSON - cjson.decode(json_string) - JSON转Lua table
总结
本篇笔记介绍了Lua的高级语法、OpenResty的安装配置以及如何在OpenResty中实现业务逻辑。通过封装HTTP请求工具和处理JSON数据,我们能够实现从OpenResty到Tomcat的请求转发,为多级缓存架构奠定了基础。这些技术使得我们可以在Nginx层面处理业务逻辑,减少对后端服务的直接依赖。