寫前端的朋友不知道如何拓展自己在后端的能力,那么nodejs是你的不二選擇,廢話不多說,直接進入正題。
這里我演示的是nodejs+mysql,別的數據庫也類似。
首先我們需要做兩件事,下載nodejs和mysql安裝,這些基本知識略過。
接著新建一個文件夾,在此文件夾下打開cms,或者vscode的終端,輸入node init初始化一個項目,輸入一些基本信息。
然后我們我們還需要安裝以下包到--save下
express和mysql這兩個包是最主要的,稍后再講其他包的作用。
在這里我要闡明一個事實,這里的mysql是操作mysql數據庫的一個js插件,并不是數據庫軟件,npm下載的包都是一些js的插件包。
好了,接下來和我一步步向下操作就可以了。
在文件夾下新建一個index.js文件,當然別的名字也可以,這個文件是你整個程序的入口。
鍵入以下代碼:
80代表的是你的端口號,然后在終端或者cms輸入node index.js,在瀏覽器里打開localhost就可以看到了,或者127.0.0.1也行,如果是別的端口號需要加上端口號,當然現在是什么也沒有,因為我們還沒有寫接口。
接下來我們寫一個get接口,返回一個‘hello world’字符串
res.json這個方法是以json對象的形式返回去,還有以下方法
res.send以頁面的方式返回去
res.download以文件的方式返回去,前端請求會下載此文件
別的方法這里就不在一一闡明了,可以打出res.然后使用vscode的語法提醒查看下面的方法即可,或者查看文檔看解釋。
接下來我們返回一個頁面:
可以看到localhost頁面上出現了我們預期的結果
到了這里想必你們已經發現問題了,我每次改動一下都要重新跑程序,這不符合人體工程學,說的一點沒錯,我無法容忍,你萌呢?
想必你們在前面也發現了pageage.json里有這么一句話
scripts的作用就是自己定義腳本命令,在這下面定義的所有命令都可以使用npm run xxx來運行,可以省略run。里面運行的應該是node index.js才對,但是這里我們使用了一個插件,hotnode,這個插件可以讓你的node程序熱更新,要全局安裝這個插件,不然找不到命令。
npm install -g hotnode
然后我們就可以npm start運行我們的程序了,所有基于node的程序跑起來都是兩步,npm install,安裝所有插件,npm start運行程序,如果跑不起來,那么這個項目一定不是一個好項目,我通常如此告誡我的弟子,我們一定要站在巨人的肩上。
做到這里,我們接下來就可以愉快的開發了。
接下來我們試試post方法
post不支持瀏覽器直接訪問,這個時候要用postman軟件
依然符合我們的預期。
可以把路徑改為/login,/test進行嘗試,這里就不再演示了。
也可以試試app.all方法,這個方法支持所有請求方式,不必每個請求都寫好幾遍了。
想必大家已經想到了,我要做登錄攔截難道每個接口里都要寫一遍嗎。
答案是當然不用的,接口的第一個參數可以用正則表達,我們這么寫:
我們使用來匹配所有路徑,這個時候請求test,會先經過,被攔截返回了**,
我們可以在內部判斷來進行操作:
如果未登錄,返回未登錄,否則,繼續向下匹配,回調函數接收三個參數,最后一個是next,繼續向下執行,路徑一定要寫在最上面,不然會先被test捕捉到,test沒有執行next,就會捕捉不到請求。
這時候就可以設置login的值來看路徑localhost/test下的返回值了。
那么有參數的情況呢,我們先引入一下中間件,如果沒有安裝可以先npm安裝
接下來我們請求一下
?后面的表單參數會放到req.query里,路徑上的參數會放到req.params里,json參數會放到req.body里,可以任意選擇一種參數傳遞即可,路徑以:開頭表示此路徑作為參數的意思。
前后端聯調的時候經常碰到跨域的問題,我們可以使用cors插件解決,
以上提到的跨域和參數都可以自己進行處理,利用路徑自己提取參數,在*路徑的請求的請求體req里自己加上跨域允許的header,但我希望你們可以使用插件,保證代碼的簡潔性,同時
我經常告訴我的弟子,我們一定要站在巨人的肩上。
好了,接下來我們開始連接數據庫,從數據庫里拿一條數據出來返回給前端。
引入mysql插件,我們先在mysql里新建一個表students,存入以下數據:
然后使用mysql插件連接數據庫
option里都是連接數據庫的基本配置,更多參數可以查看文檔,我們請求一下localhost/login看看
真的返回了我們存在數據庫的數據,我好激動啊,大業終于完成了。
是的,conn.query就是執行一條sql語句,在回調函數里返回結果。
結果可以用構造函數封裝,這樣就不用每次都寫一推沒用的字段了。
如果你在此處這樣做:
那么這個不妥的,第一次沒有問題,第二次不行了,說是關閉了數據庫無法繼續查詢,因為connect()并不能重連數據庫,你需要重新建立一條新連接,所以不建議使用conn.end()斷開數據庫。
如果莫名其妙斷了呢,我們就需要就重連機制,斷了數據庫會觸發error事件,我們這樣處理:
監聽error事件,如果err.code返回了以上字符,那么我們就重新發起連接,直到連接成功。
做到這里,想必大家已經想到了,這是單線程的,并發量高的時候會不會頂不住,會的,所以我們要上連接池。
連接池與連接相似,做以下處理:
建立連接池比連接多了幾個參數,這里羅列了常用的三個,其它參數可以查看文檔。箭頭處多處理了一下斷線重連,我在服務里關掉mysql服務再打開測試了一遍,功能正常、這個時候我們使用連接池處理請求。conn.release()的意思是釋放連接池的意思,用完就要釋放給別的請求使用,也可以直接使用連接池,具體區別我還不知道,我猜應該是直接使用連接池就是這個線程專門為這個請求服務,不用別的也不釋放,可以用于常用接口,可以減少取連接池的操作。
做到這里我們大部分工作已經做完了,想必大家一定又想到了什么,我如果有一千個接口,難道要在一個文件里寫一千個嗎。
這當然是不妥的,比較難維護,所以我們要拆分模塊,使用express.Router()這個api。
我們將連接數據庫的文件單獨抽離
導出常用的pool,Result,router,app模塊,然后在子模塊:
然后在入口:
看看是不是簡潔多了,要注意一點,引入的子模塊要放到全局監聽的下面,不然又會無法匹配到,app.use的第一個參數代表下發到那個目錄,內部子模塊的/相當于app.use的第一個參數,express()和express.Router()的區別是,router比較小,可以作為中間件。接下來請求一下/和/login試試吧。