1. 程式人生 > >WEB介面開發思路和基本方法

WEB介面開發思路和基本方法

想要對OpenWRT的WEB介面(*下稱介面)進行修改。修改的目標是:

1.修改頁面的樣式,設計為企業的風格(stylesheet)

2.新建自己的功能,實現 訪問頁面後,使用者就可以對配置檔案(也就是系統的一些引數)進行修改。 甚至是與遠端伺服器互動,實現驗證。

一. 幾種可行的開發路線:

1.改用PHP、JSP等語言開發

2.修改已有的介面,實現自己的功能

  2.1 修改已有樣式表

  2.2 仍然利用lua開發

第一種比較容易操作,但需要在裝置裡安裝nginx和PHP環境,然後在 /www下放PHP指令碼就可以了。但是這種方法可能對閘道器裝置的儲存帶來較大壓力。所以我沒有采取這種方式。(這個就是普通的web開發,只不過多了一些對檔案的讀寫,字元格式的匹配,還有要去操作一些linux shell命令。 前期我也開發了一個這個版本,但是後來被廢棄啦。如果想用這種方式開發的歡迎來交流。)

第二種中有兩種方式,這是我想分享的兩種開發模式。接下來簡單介紹一下。

二.LuCI的檔案目錄

1.

OpenWRT luci中,web介面在/www下。其他的介面由CGI程式生成。 /www下放有index.html,僅僅用來直接跳轉至 /cgi-bin/luci 。

2.

CGI程式實質上是MVC模式。M~model,V~view,C~controller。MVC讀取配置檔案的資訊,然後輸出到頁面上,也就是MVC裡面的讀“資料庫”,寫“資料庫”。只不過這裡面的“資料庫”對應的是配置檔案,讀寫方法也不太一樣。

Model(配置檔案):/etc/config

View(頁面檔案):/usr/lib/lua/luci/view

Controller(控制器):/usr/lib/lua/luci/Controller

請注意:View(頁面檔案)的stylesheet(樣式表文件)地址是 /www/luci-static/bootstrap/cascade.css

3.

view、controller根據功能進行分組後存在不同的資料夾內。比如狀態功能以及狀態功能下的總覽、防火牆等功能的view會存在admin-status資料夾下面。檔案的儲存路徑恰好與訪問功能的url一致(為http://192.168.1.1/cgi-bin/luci/admin/status/xxx)。

三.第二種方法示例

剛才說到,對介面進行開發有兩種方式。這裡先介紹主流的第二種方式。這種方式的優點是 能夠自由自在的定義樣式(我覺得重繪介面肯定比按照介面元素去挨個修改介面樣式容易很多。猜想您的前端一定也會很感謝你使用了這種方法來進行開發~)

以及將業務邏輯進行簡單歸類,並且可以自由訂製表單介面的樣式和差異性(如果您暫時不能理解這點,請先跳過,看完全文後在回來分析這句話)。

controller中,url和您想要操作的行為有三種對應方式,這麼說太磨嘰了,不懂。簡而言之就是:

url可以對應htm頁面“讀寫資料庫”,url可以呼叫一個方法“讀或者寫,也可以對資料進行操作”,url可以呼叫一個cbi方法,來“寫資料庫”。

html並不是傳統意義上的靜態頁面。事實上,可以在.htm檔案內使用lua的方法。

那麼接下來簡單介紹一下如何修改伺服器檔案。我以修改裝置名字做示例。

首先,寫一個htm檔案,裡面存著表單。

檔案儲存在/usr/lib/lua/luci/view下,檔名叫 setHostname.htm,檔案內容如下。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SET-HOSTNAME</title>
</head>
<body>
<p>Setting the IP address</p>
<form method="get" action="<%=luci.dispatcher.build_url("set", "hostname")%>">
<input type="text" name="hostname">
<button id="submit">提交</button>
</form>
</body>
</html>

好了,v 睪丸了,然後該弄controller了。我要能根據url訪問到表單,還要寫一個響應表單請求的頁面(方法)能夠使得檔案的修改生效。

開啟一個controller的檔案。請注意這裡不限定究竟開啟哪個controller的檔案。但是為了保證專案程式碼的易維護性,最好還是新建一個controller。在/usr/lib/lua/luci/controller下可以新建一個mytest.lua(或者mkdir一個test資料夾再新建mytest.lua

mytest.lua的檔案內容是:

module("luci.controller.mytest", package.seeall)

function index(){

  entry({"fuck", "ybt", "sb"}, template("setHostname"))

  entry({"set", "hostname"}, call("set_hostname"))

}

function set_hostname()

  local hostname = luci.http.formvalue("hostname")

  local executeString = "uci set [email protected][0].hostname="..hostname

  luci.sys.exec(executeString)

 end

好了,寫完了這些之後,清除快取 / 重啟uhttpd / reboot就可以使對頁面的修改生效。

清除快取方法:清除/tmp下面所有luci-xxxx資料夾。 命令:rm /tmp/luci-* -rf

建議您把 -rf 寫在後面,以防止無心之失。

重啟uhttpd:/etc/init.d/uhttpd restart

reboot:這是終極大招。如果前兩種方式都沒有使介面修改生效,再考慮此方法吧~ btw ,reboot之後,你就可以斷掉與路由的ssh了。因為你需要重新ssh這個路由器。 命令: reboot

接下來,訪問192.168.1.1/cgi-bin/luci/fuck/ybt/sb 來對頁面進行修改。然後頁面會使用get的方法給192.168.1.1/cgi-bin/luci/set/hostname 傳過去一個值。

192.168.1.1/cgi-bin/luci/set/hostname將呼叫控制器內部的set_hostname方法,設定hostname的值。

Knowledges

1.主機名存放的檔案地址:/etc/config/system

這個檔案的檔案內容是:

config system
option zonename 'UTC'
option timezone 'GMT0'
option conloglevel '8'
option cronloglevel '8'
option hostname 'ybtsb'

config timeserver 'ntp'
list server '0.openwrt.pool.ntp.org'
list server '1.openwrt.pool.ntp.org'
list server '2.openwrt.pool.ntp.org'
list server '3.openwrt.pool.ntp.org'
option enabled '1'

現在主機名是ybtsb 。這個是我可愛的室友的名字。

2.controller是如何實現了對檔案的修改呢?
controller中的lua語法呼叫了luci框架本身的方法,去執行一句shell語句。

luci.sys.exec("語句")

這個語句可以是任何的shell。

比如剛才提到的清理快取:luci.sys.exec("rm /tmp/luci-* -rf")

再比如reboot。 local ybtsb="reboot" luci.sys.exec(ybtsb) 這裡的ybtsb是一個變數。具體lua的語法,請訪問lua的官方網站。本案的開發只涉及呼叫一些uci的shell。故不做展開。

那麼,修改檔案的shell是:

uci set A.B.C=value A是檔名,B是節名,C是配置項名。value是要把C對應的項進行修改的變數

當然,聰明的你應該猜到了,從檔案中獲取配置項的shell是uci get A.B.C

我們來看一看閘道器的IP地址。閘道器的IP地址存放在/etc/config/network檔案下lan節的ipaddr

我們先vi一下這個檔案。vi /etc/config/network 這個檔案是醬紫的:

Markdown

紅色的部分我把它叫節(B)。裡面的每一項叫做配置項(C)。

我們看到network下面的lan節下面的ipaddr是 192.168.1.1

ok 退出這個檔案的編輯( esc -> :q!)。

執行命令:uci get network.lan.ipaddr 回車
得到的內容是 192.168.1.1

當然,如果你想修改ipaddr,可以用shell :uci get network.lan.ipaddr=192.168.1.2

….

你可能會注意到 前面修改hostname的時候,用到了@和[0]這種意味不明的東西。這是怎麼回事呢?

事實上/etc/config下的配置檔案中,可能含有多個含有相同節名(或者不含節名的)配置檔案。怎麼能夠準確調取捏?

如果重名,[ 0 ] [ 1 ] 放在節的後面,依次對應著檔案內的同名節第一項和第二項。順序由其在檔案內的先後順序決定。

如果沒名,就如同剛才的system檔案:

B的部分,寫節的類。要用@做標記,並標記先後 如上面獲取hostname,就應該用uci get [email protected][0].hostname

當然!htm中也可以使用lua語句然後調取檔案的內容。這個方法很簡單:

在你想要呼叫的htm檔案中這樣使用:

<!--Lua Code start here-->

<%

    local ip=luci.sys.exec("uci get network.lan.ipaddr")

%>

<p>IP地址是:<%=ip%></p>

OK了 以上兩個案例涵蓋了這種開發方式的最基本操作。當然,有些時候你可能需要對輸入和輸出資料格式進行調整。你可以在htm的lua程式碼段和控制器的方法中編寫方法。具體內容請 100度 - -

最後是這種開發方式的開發思路:

1.看文件,瞭解你要修改的的配置項 在 那個檔案中?

2.寫controller,包括form target的地址和其他可訪問頁面的地址。

3.寫html css 畫介面。

4.在controller中編寫資料處理函式。luci中也有trim函式哦(具體內容,請100度 )。

5.最後,為了提升使用者體驗,form頁應該使用ajax來傳輸資料。

四.第一種方法開發

注意到剛才controller的url對應中沒有提及cbi。cbi幹嘛用的呢?說白了就是一行程式碼生成一個表單頁面。這個頁面裡有一個input和button。直接對應配置檔案中的相關節和相關項。具體使用,請參見github.com/openwrt/luci/wiki/ 下面的howto。

cbi能夠直接生成表單,也意味著它的高度封裝給我們自定義web介面帶來了困難。我們不僅無法直觀修改cbi的頁面樣式,也不能自由自在的使用JavaScript。

直接使用lua的方法,我個人認為比較簡潔。歡迎大家一同討論openwrt web介面開發中所遇到的困難。

——————————————————

(C)Sugarguan

[email protected] 2018.06.21

Poi.Harbin Institute of Technology