寫(xiě)前端的朋友不知道如何拓展自己在后端的能力,那么nodejs是你的不二選擇弄兜,廢話不多說(shuō)讥电,直接進(jìn)入正題御毅。
這里我演示的是nodejs+mysql,別的數(shù)據(jù)庫(kù)也類似羽杰。
首先我們需要做兩件事渡紫,下載nodejs和mysql安裝,這些基本知識(shí)略過(guò)考赛。
接著新建一個(gè)文件夾惕澎,在此文件夾下打開(kāi)cms,或者vscode的終端,輸入node init初始化一個(gè)項(xiàng)目颜骤,輸入一些基本信息唧喉。
然后我們我們還需要安裝以下包到--save下
express和mysql這兩個(gè)包是最主要的,稍后再講其他包的作用复哆。
在這里我要闡明一個(gè)事實(shí)欣喧,這里的mysql是操作mysql數(shù)據(jù)庫(kù)的一個(gè)js插件,并不是數(shù)據(jù)庫(kù)軟件梯找,npm下載的包都是一些js的插件包唆阿。
好了,接下來(lái)和我一步步向下操作就可以了锈锤。
在文件夾下新建一個(gè)index.js文件驯鳖,當(dāng)然別的名字也可以,這個(gè)文件是你整個(gè)程序的入口久免。
鍵入以下代碼:
80代表的是你的端口號(hào)浅辙,然后在終端或者cms輸入node index.js,在瀏覽器里打開(kāi)localhost就可以看到了阎姥,或者127.0.0.1也行记舆,如果是別的端口號(hào)需要加上端口號(hào),當(dāng)然現(xiàn)在是什么也沒(méi)有呼巴,因?yàn)槲覀冞€沒(méi)有寫(xiě)接口泽腮。
接下來(lái)我們寫(xiě)一個(gè)get接口御蒲,返回一個(gè)‘hello world’字符串
res.json這個(gè)方法是以json對(duì)象的形式返回去,還有以下方法
res.send以頁(yè)面的方式返回去
res.download以文件的方式返回去诊赊,前端請(qǐng)求會(huì)下載此文件
別的方法這里就不在一一闡明了厚满,可以打出res.然后使用vscode的語(yǔ)法提醒查看下面的方法即可,或者查看文檔看解釋碧磅。
接下來(lái)我們返回一個(gè)頁(yè)面:
可以看到localhost頁(yè)面上出現(xiàn)了我們預(yù)期的結(jié)果
到了這里想必你們已經(jīng)發(fā)現(xiàn)問(wèn)題了碘箍,我每次改動(dòng)一下都要重新跑程序,這不符合人體工程學(xué)鲸郊,說(shuō)的一點(diǎn)沒(méi)錯(cuò)丰榴,我無(wú)法容忍,你萌呢严望?
想必你們?cè)谇懊嬉舶l(fā)現(xiàn)了pageage.json里有這么一句話
scripts的作用就是自己定義腳本命令多艇,在這下面定義的所有命令都可以使用npm run xxx來(lái)運(yùn)行,可以省略run像吻。里面運(yùn)行的應(yīng)該是node index.js才對(duì)峻黍,但是這里我們使用了一個(gè)插件,hotnode拨匆,這個(gè)插件可以讓你的node程序熱更新姆涩,要全局安裝這個(gè)插件,不然找不到命令惭每。
npm install -g hotnode
然后我們就可以npm start運(yùn)行我們的程序了骨饿,所有基于node的程序跑起來(lái)都是兩步,npm install,安裝所有插件台腥,npm start運(yùn)行程序宏赘,如果跑不起來(lái),那么這個(gè)項(xiàng)目一定不是一個(gè)好項(xiàng)目黎侈,我通常如此告誡我的弟子察署,我們一定要站在巨人的肩上。
做到這里峻汉,我們接下來(lái)就可以愉快的開(kāi)發(fā)了贴汪。
接下來(lái)我們?cè)囋噋ost方法
post不支持瀏覽器直接訪問(wèn),這個(gè)時(shí)候要用postman軟件
依然符合我們的預(yù)期休吠。
可以把路徑改為/login扳埂,/test進(jìn)行嘗試,這里就不再演示了瘤礁。
也可以試試app.all方法阳懂,這個(gè)方法支持所有請(qǐng)求方式,不必每個(gè)請(qǐng)求都寫(xiě)好幾遍了。
想必大家已經(jīng)想到了希太,我要做登錄攔截難道每個(gè)接口里都要寫(xiě)一遍嗎克饶。
答案是當(dāng)然不用的酝蜒,接口的第一個(gè)參數(shù)可以用正則表達(dá)誊辉,我們這么寫(xiě):
我們使用來(lái)匹配所有路徑,這個(gè)時(shí)候請(qǐng)求test,會(huì)先經(jīng)過(guò)亡脑,被攔截返回了**堕澄,
我們可以在內(nèi)部判斷來(lái)進(jìn)行操作:
如果未登錄,返回未登錄霉咨,否則蛙紫,繼續(xù)向下匹配,回調(diào)函數(shù)接收三個(gè)參數(shù)途戒,最后一個(gè)是next,繼續(xù)向下執(zhí)行坑傅,路徑一定要寫(xiě)在最上面,不然會(huì)先被test捕捉到喷斋,test沒(méi)有執(zhí)行next,就會(huì)捕捉不到請(qǐng)求唁毒。
這時(shí)候就可以設(shè)置login的值來(lái)看路徑localhost/test下的返回值了。
那么有參數(shù)的情況呢星爪,我們先引入一下中間件浆西,如果沒(méi)有安裝可以先npm安裝
接下來(lái)我們請(qǐng)求一下
?后面的表單參數(shù)會(huì)放到req.query里顽腾,路徑上的參數(shù)會(huì)放到req.params里近零,json參數(shù)會(huì)放到req.body里,可以任意選擇一種參數(shù)傳遞即可抄肖,路徑以:開(kāi)頭表示此路徑作為參數(shù)的意思久信。
前后端聯(lián)調(diào)的時(shí)候經(jīng)常碰到跨域的問(wèn)題,我們可以使用cors插件解決漓摩,
以上提到的跨域和參數(shù)都可以自己進(jìn)行處理裙士,利用路徑自己提取參數(shù),在*路徑的請(qǐng)求的請(qǐng)求體req里自己加上跨域允許的header幌甘,但我希望你們可以使用插件潮售,保證代碼的簡(jiǎn)潔性,同時(shí)
我經(jīng)常告訴我的弟子锅风,我們一定要站在巨人的肩上酥诽。
好了,接下來(lái)我們開(kāi)始連接數(shù)據(jù)庫(kù)皱埠,從數(shù)據(jù)庫(kù)里拿一條數(shù)據(jù)出來(lái)返回給前端肮帐。
引入mysql插件,我們先在mysql里新建一個(gè)表students,存入以下數(shù)據(jù):
然后使用mysql插件連接數(shù)據(jù)庫(kù)
option里都是連接數(shù)據(jù)庫(kù)的基本配置训枢,更多參數(shù)可以查看文檔托修,我們請(qǐng)求一下localhost/login看看
真的返回了我們存在數(shù)據(jù)庫(kù)的數(shù)據(jù),我好激動(dòng)啊恒界,大業(yè)終于完成了睦刃。
是的,conn.query就是執(zhí)行一條sql語(yǔ)句十酣,在回調(diào)函數(shù)里返回結(jié)果涩拙。
結(jié)果可以用構(gòu)造函數(shù)封裝,這樣就不用每次都寫(xiě)一推沒(méi)用的字段了耸采。
如果你在此處這樣做:
那么這個(gè)不妥的兴泥,第一次沒(méi)有問(wèn)題,第二次不行了虾宇,說(shuō)是關(guān)閉了數(shù)據(jù)庫(kù)無(wú)法繼續(xù)查詢搓彻,因?yàn)閏onnect()并不能重連數(shù)據(jù)庫(kù),你需要重新建立一條新連接嘱朽,所以不建議使用conn.end()斷開(kāi)數(shù)據(jù)庫(kù)旭贬。
如果莫名其妙斷了呢,我們就需要就重連機(jī)制燥翅,斷了數(shù)據(jù)庫(kù)會(huì)觸發(fā)error事件骑篙,我們這樣處理:
監(jiān)聽(tīng)error事件,如果err.code返回了以上字符森书,那么我們就重新發(fā)起連接靶端,直到連接成功。
做到這里凛膏,想必大家已經(jīng)想到了杨名,這是單線程的,并發(fā)量高的時(shí)候會(huì)不會(huì)頂不住猖毫,會(huì)的台谍,所以我們要上連接池。
連接池與連接相似吁断,做以下處理:
建立連接池比連接多了幾個(gè)參數(shù)趁蕊,這里羅列了常用的三個(gè),其它參數(shù)可以查看文檔仔役。箭頭處多處理了一下斷線重連掷伙,我在服務(wù)里關(guān)掉mysql服務(wù)再打開(kāi)測(cè)試了一遍,功能正常又兵、這個(gè)時(shí)候我們使用連接池處理請(qǐng)求任柜。conn.release()的意思是釋放連接池的意思卒废,用完就要釋放給別的請(qǐng)求使用,也可以直接使用連接池宙地,具體區(qū)別我還不知道摔认,我猜應(yīng)該是直接使用連接池就是這個(gè)線程專門為這個(gè)請(qǐng)求服務(wù),不用別的也不釋放宅粥,可以用于常用接口参袱,可以減少取連接池的操作。
做到這里我們大部分工作已經(jīng)做完了粹胯,想必大家一定又想到了什么蓖柔,我如果有一千個(gè)接口,難道要在一個(gè)文件里寫(xiě)一千個(gè)嗎风纠。
這當(dāng)然是不妥的,比較難維護(hù)牢贸,所以我們要拆分模塊竹观,使用express.Router()這個(gè)api。
我們將連接數(shù)據(jù)庫(kù)的文件單獨(dú)抽離
導(dǎo)出常用的pool,Result,router,app模塊潜索,然后在子模塊:
然后在入口:
看看是不是簡(jiǎn)潔多了臭增,要注意一點(diǎn),引入的子模塊要放到全局監(jiān)聽(tīng)的下面竹习,不然又會(huì)無(wú)法匹配到誊抛,app.use的第一個(gè)參數(shù)代表下發(fā)到那個(gè)目錄,內(nèi)部子模塊的/相當(dāng)于app.use的第一個(gè)參數(shù)整陌,express()和express.Router()的區(qū)別是拗窃,router比較小,可以作為中間件泌辫。接下來(lái)請(qǐng)求一下/和/login試試吧随夸。