Lua Web快速開發(fā)指南(2) - cf的運(yùn)行機(jī)制簡(jiǎn)介與基于httpd庫(kù)的開發(fā)環(huán)境搭建

2019-06-18 22:53 更新

從本章開始假設(shè)大家都熟悉lua語(yǔ)法.

運(yùn)行流程

在上一章節(jié)學(xué)會(huì)了如何安裝cf后, 本章節(jié)就會(huì)介紹cf到運(yùn)行機(jī)制與httpd的server搭建!

cf是一個(gè)非常典型的基于協(xié)程的事件驅(qū)動(dòng)開發(fā)框架在封裝成API后, 可以依賴事件循環(huán)執(zhí)行一套穩(wěn)定運(yùn)行時(shí)環(huán)境.

而lua本身提供了強(qiáng)大的table數(shù)據(jù)結(jié)構(gòu)可以根據(jù)需要自行構(gòu)建所謂的"config", 所以cf為了減少無(wú)用的依賴就沒(méi)有提供額外的config文件進(jìn)行配置.

cf會(huì)假設(shè)所有業(yè)務(wù)代碼文件都在script目錄下, 所以建議您在script下自行劃分好文件的目錄歸屬.

cf將所有業(yè)務(wù)編寫的腳本目錄命名為script, script目錄下點(diǎn)main.lua文件將會(huì)是入口文件. 這個(gè)main.lua執(zhí)行完畢之后才會(huì)真正進(jìn)入事件循環(huán).

在執(zhí)行完成script/main.lua文件后, cf則會(huì)是實(shí)際情況決定是否需要開始運(yùn)行事件循環(huán). 假設(shè)開發(fā)者僅僅想運(yùn)行print("hello world"), 那么cf將會(huì)在main.lua執(zhí)行完成后直接退出.

運(yùn)行機(jī)制的問(wèn)題與模塊化的設(shè)計(jì)

main.lua文件內(nèi)部可以導(dǎo)入其它lua代碼進(jìn)行模塊化設(shè)計(jì), 但是有一點(diǎn)需要注意的是: cf框架在使用require導(dǎo)入文件時(shí), 導(dǎo)入的文件只能用于定義不可用于流程執(zhí)行.

什么意思呢? 例如, 當(dāng)你在使用創(chuàng)建一個(gè)httpd實(shí)例之前會(huì)先創(chuàng)建DB對(duì)象并且進(jìn)行初始化! 這時(shí)候您可以回設(shè)計(jì)像下面的代碼:

  -- mydb.lua
  local DB = require "DB"
  local db = DB:new {
    host = "localhost",
    port = 3306,
    database = "cfadmin",
    charset = 'utf8'
    -- ...
  }
  local ok = db:connect()
  if not ok then
    return nil
  end
  return db

  -- main.lua
  local db_cls = require "mydb"
  --[[
  ... do your want do
  ]]

這樣做你會(huì)得到一個(gè)錯(cuò)誤提示:"attempt to yield from outside a coroutine", 這個(gè)錯(cuò)誤提示的中文大概意思就是: "不能在非協(xié)程的環(huán)境下切換執(zhí)行權(quán)".

這是因?yàn)閞equire函數(shù)的對(duì)指定的腳本調(diào)用的Call方法使其不允許臨時(shí)切換出執(zhí)行權(quán), 而初始化數(shù)據(jù)庫(kù)連接操作是依賴cf的協(xié)程與異步操作所以就會(huì)導(dǎo)致上面的錯(cuò)誤出現(xiàn).

可以將mydb.lua與main.lua的代碼替換成下面這樣(Cache庫(kù)同理)來(lái)解決:

  -- mydb.lua
  local DB = require "DB"


  local db


  return function ()
    if db then
      return db
    end
    db = DB:new {
      host = "localhost",
      port = 3306,
      database = "cfadmin",
      charset = 'utf8'
      -- ...
    }
    local ok = db:connect()
    if not ok then
      db:close()
      db = nil
      return nil, "連接失敗"
    end
    return db
  end

  -- main.lua
  local get_db = require "mydb"
  local db = get_db()
  -- [[
  ... do your want do
  ]]

這是用一種巧妙的function與upvalue的方式避開了require的內(nèi)部call調(diào)用, require返回后執(zhí)行權(quán)重新回到了由cf啟動(dòng)的協(xié)程中. 這樣就可以開始正確初始化了.

這種情況僅限于依賴require執(zhí)行某段異步代碼塊的時(shí)候, 其它情況下一般不會(huì)出現(xiàn)問(wèn)題. 優(yōu)質(zhì)的項(xiàng)目管理人員一般不會(huì)出現(xiàn)這樣的設(shè)計(jì).

使用httpd庫(kù)快速搭建lua web開發(fā)環(huán)境

httpd庫(kù)是cf內(nèi)置的基于http 1.1協(xié)議開發(fā)的web server! 高效解析器是必不可少的, httpd庫(kù)使用picohttpparser解析器來(lái)構(gòu)建http context.

我們假設(shè)您至少看過(guò)httpd庫(kù)的API Reference, 并且至少知道下面所述的API.

此處所有的API與使用方式都將會(huì)在API Reference中找到.

1. 導(dǎo)入http庫(kù)

httpd庫(kù)位于app/lualib下, 使用者可以在main.lua文件內(nèi)直接使用local httpd = require "httpd"導(dǎo)入httpd庫(kù).

2. 初始化一個(gè)httpd app對(duì)象

httpd庫(kù)使用lua class對(duì)象進(jìn)行創(chuàng)建! 默認(rèn)提供了new方法, 使用者可以使用new方法創(chuàng)建一個(gè)httpd的app實(shí)例.

  local httpd = require "httpd"


  local app = httpd:new("app")

3. 注冊(cè)靜態(tài)文件路徑

httpd提供給了內(nèi)置的靜態(tài)文件查找能力, 只需要使用者自動(dòng)使用static方法注冊(cè)靜態(tài)文件路徑即可.

  app:static("static", 30)

static表示使用者想將app/static文件夾當(dāng)做靜態(tài)文件的根目錄.

4. 設(shè)置監(jiān)聽(tīng)端口

httpd啟動(dòng)需要指定監(jiān)聽(tīng)的端口, 默認(rèn)監(jiān)聽(tīng)所有網(wǎng)卡. 雖然沒(méi)有使用第一個(gè)參數(shù), 但是不可為空.

  app:listen("0.0.0.0", 8080)

5. 運(yùn)行

在初始化完成后, app調(diào)用run方法將會(huì)啟動(dòng)httpd服務(wù)器. run方法后面的代碼可能永遠(yuǎn)不會(huì)有機(jī)會(huì)執(zhí)行.

  app:run()

6. 運(yùn)行cf

使用./cfadmin命令運(yùn)行httpd server, 如果您看到類似運(yùn)行等字樣說(shuō)明httpd服務(wù)已經(jīng)啟動(dòng)完成, 否則將會(huì)有響應(yīng)的錯(cuò)誤提示.

7. 完整的代碼示例

-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("app")


app:static("static", 30)


app:listen("0.0.0.0", 8080)


app:run()

體驗(yàn)一下

現(xiàn)在, 讓我們打開http://localhost:8080/index.html查看是否能正確顯示頁(yè)面了呢?

更多的httpd API

這里你可以找到更多有關(guān)httpd庫(kù)的API說(shuō)明.

繼續(xù)學(xué)習(xí)

一下章我們一起學(xué)習(xí)如何用cf來(lái)注冊(cè)注冊(cè)路由

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)