Node.js框架--Express
Express 的特點:
-
易上手
-
高效能
-
擴充套件性強:可以自由的拆分和安裝模組
安裝 Express
// 示例:使用 express 快速搭建一個伺服器 const express = require('express'); const app = express(); app.get('/', (req, res)=>{ res.send('<h1>Hello Express</h1>') }).listen(3000,()=>{ console.log('伺服器已經啟動...'); })
Express 本質是一個非常簡潔的框架,這個框架本身只是由中介軟體
中介軟體
本身正常的過程是傳送請求到伺服器,伺服器端對請求進行處理,然後給客戶端響應。中介軟體就是在接收到前端的請求後,做出的一系列的工作。
// 下面是一箇中間件的示例 function 中介軟體的名字(req, res, next){ // req 代表 http 請求 // res 代表 http 響應 // next 呼叫下一個中介軟體 }
app.use(中介軟體的名字); //註冊中介軟體
中介軟體的使用(註冊:use)的順序是很重要的。後面我們在使用中介軟體的時候,一定要注意中介軟體的前後順序關係。
一般來講,我們不會涉及到自己書寫中介軟體,一般都是使用第三方的中介軟體。
下面以 body-parser 中介軟體為例
安裝 body-parser
npm i body-parser
具體方法
// 示例:使用 express 快速搭建一個伺服器 const express = require('express'); const app = express(); const bodyParser = require('body-parser'); // 引入第三方中介軟體 // 註冊中介軟體 // 這邊註冊 bodyParser 的時候,設定一下解析規則 // 原生的 node,如果要獲取 post 請求的資料,需要監聽事件 // data,end,bodyParser 就可以讓我們很輕鬆的獲取到 post 請求的資料 app.use(bodyParser.urlencoded({extended : false})); app.use(bodyParser.json()); // 把資料解析成 json 物件 let str = ` <form method="POST" action=""> <div> name : <input type="text" name="username"> </div> <div> age : <input type="text" name="userage"> </div> <button>提交</button> </form> ` app.use('/', (req, res)=>{ if(req.body.username && req.body.userage){ console.log('拿到了客戶端post 請求的資料'); console.log(`資料為:${req.body.username},${req.body.userage}`); res.send(`name 為${req.body.username},age 為${req.body.userage}`); } else { res.send(str); } }).listen(3000,()=>{ console.log('伺服器已經啟動...'); })
路由
所謂路由,就是對客戶端的請求進行合適的導航。
從 express 4.0 開始,路由已經成為了一個單獨的中介軟體,並且這個中介軟體是 express 內建。
// index.js // 示例:使用 express 快速搭建一個伺服器 const express = require('express'); const app = express(); const router = require('./router'); // 所以我們需要設定路由將使用者不同的 url 導航到不同的頁面 app.use('/', router); app.listen(3000,()=>{ console.log('伺服器已經啟動...'); }) // router.js // 這個就是我的路由檔案 // 專門用來管理應用程式的路由 const express = require('express'); const router = express.Router(); // 之後所有的路由配置都掛在這個 router 上面 router.get('/',(req,res)=>{ res.send('這是首頁'); }) router.get('/contact',(req,res)=>{ res.send('這是聯絡我們'); }) router.get('/detail',(req,res)=>{ res.send('這是商品詳情'); }) module.exports = router;
靜態資源的託管
什麼是靜態資源?
所謂靜態資源,就是指 html,css,圖片,圖示,字型,這些都是靜態資源。
在 express 中內建了一箇中間件,專門用來管理靜態資源。
app.use(express.static(靜態資源的目錄));
__dirname:當前所在的目錄 __filename:當前檔案所在位置 例如: console.log(__dirname); // /Users/Jie/Desktop/demo console.log(__filename); // /Users/Jie/Desktop/demo/index.js
接下來,我們來設定該專案的靜態資源目錄,程式碼如下:
// 示例:使用 express 快速搭建一個伺服器 const express = require('express'); const app = express(); const router = require('./router'); // 所以我們需要設定路由將使用者不同的 url 導航到不同的頁面 app.use(express.static(__dirname + '/public')) app.use('/', router); app.listen(3000,()=>{ console.log('伺服器已經啟動...'); })
express 腳手架
大家一聽到腳手架,第一反應就是工地上的腳手架,就是那個東西。腳手架和工地上的腳手架其實是一個意思,就是把專案的架子搭建起來。
npm i express-generator -g
安裝完成後,我們就可以使用命令:
express <專案名>
但是搭建起來的專案,沒有依賴項,所以需要 npm i 安裝依賴。
安裝完成之後,npm start 就可以啟動了。
搭建好專案之後,接下來我們來看一下整個專案的目錄結構。
-
app.js:入口檔案
-
bin:二進位制目錄
-
node_modules:依賴包
-
package.json:依賴包的記錄檔案
-
public:靜態目錄
-
routes:路由
-
views:頁面模板
接下來,我們要來做一個具體的專案:學生管理系統
首先,我們的專案已經用 express 腳手架搭建起來了,我們也學過 mongodb
接下來我們就要把兩者結合起來,研究一下 express 搭建的專案中如何訪問mongodb
mongoose
mongoose 是一個 node.js 操作 mongodb 的驅動程式。
所謂驅動程式,就是提供了一套介面。比如,我們新買了一個滑鼠,滑鼠和我的電腦系統實際上是各自獨立,現在,我想用我的作業系統去操作滑鼠,那就需要有一套介面程式,我的作業系統,只需要去呼叫這一套介面,就可以操作滑鼠,那麼,這一套介面就是驅動程式。
nodejs 和 mongodb 也是兩個獨立的東西。要想 nodejs 去操作mongodb,我們就需要安裝相應的驅動程式才行。
首先第一步,安裝 mongoose
npm i mongoose
接下來,我們來看一下 mongoose 的使用步驟:
-
建立資料模型
-
在資料模型的基礎上呼叫各種方法來操作 mongodb 資料庫
接下來,我們 來一步一步的做,首先第一步,建立一個 db.js ,該檔案負責連線資料庫,程式碼如下:
// 該檔案負責書寫連線資料庫的相關配置 const mongoose = require('mongoose'); // 連線資料庫的字串,說明要連線 f71 資料庫 const dbURI = 'mongodb://localhost/f71'; mongoose.connect(dbURI,{useNewUrlParser : true, useUnifiedTopology : true}); mongoose.connection.on('connected',()=>{ console.log('資料庫已經連線...'); })
接下來,我們就需要建立資料模型,在專案根目錄程式碼建立一個 stuModel 的檔案,這個檔案就是學生模型,程式碼如下:
// 該檔案就是資料模型檔案 require('./db.js') const mongoose = require('mongoose'); // 1. 建立 Schema,Schema 就是我們資料模型的骨架 // 在建立 Schema,就需要和集合(表)進行對應 const stuSchema = new mongoose.Schema({ name : String, age : Number, gender : String, score : Number }); // 2. 根據上面建立的 Schema 來生成資料模型 // (1) model 的名字 (2)定義的 Schema (3)和資料庫的哪個集合關聯 mongoose.model('stuModel',stuSchema,'stu'); // 3. 將這個模型匯出去,後面所有的操作(增刪改查)都是基於這個模型 module.exports = mongoose.model('stuModel');
接下來,既然我們的模型已經建立好了,接下來我們就要開始使用這個模型來看一下是否能操作 mongodb 資料庫
具體程式碼如下:
const stuModel = require('./stuModel'); stuModel.find((err, data)=>{ console.log(data); })
三層架構
什麼是三層架構?
最早是來自於微軟的後端分層的思想。以前的 web 開發是重伺服器端,輕客戶端。
補充:高類聚,低耦合
所謂高類聚,就是封裝一個模組,這個模組應該儘量關心自己的功能。
所謂耦合,就是模組與模組之間的關係,低耦合,就是模組與模組之間的關係要儘量的低。
一般來講,封裝一個模組,如果該模組高類聚,那麼它必然也是低耦合。
三層架構的解釋如下:
三層架構就是為了符合“高內聚,低耦合”思想,把各個功能模組劃分為表示層(UI)、業務邏輯層(BLL)和資料訪問層(DAL)三層架構,各層之間採用介面相互訪問,並通過物件模型的實體類(Model)作為資料傳遞的載體,不同的物件模型的實體類一般對應於資料庫的不同表,實體類的屬性與資料庫表的欄位名一致。 [1]
三層架構區分層次的目的是為了 “高內聚,低耦合”。開發人員分工更明確,將精力更專注於應用系統核心業務邏輯的分析、設計和開發,加快專案的進度,提高了開發效率,有利於專案的更新和維護工作。
接下來,我們來看一下在我們的專案中,如何實現三層架構。
首先在專案根目錄下,建立 dao 和 service 目錄,dao 就是持久層,service 就是業務層,routes 就作為我們的表現層。
dao 既然作為持久層,所以,我們所有的資料庫相關的操作,都應該放進dao目錄裡面。
在 dao 層裡面新建 model 目錄,所有的 model 放進這個目錄裡面。db.js 也放進這個 dao 目錄。
stuDao.js 負責和資料庫打交道,具體程式碼如下:
const stuModel = require('./model/stuModel'); module.exports.getStuDao = async function(){ return await stuModel.find(); }
dao 層操作資料庫拿到的資料傳遞給業務層,程式碼如下:
// 這一層就是我們的業務層 const {getStuDao} = require('../dao/stuDao'); module.exports.getStuService = async function(){ return await getStuDao() }
業務層的程式碼又會傳遞給表現層,程式碼如下:
var express = require('express'); var router = express.Router(); // 引入業務層的方法 const {getStuService} = require('../service/stuService'); /* GET home page. */ router.get('/stu', async function(req, res, next) { res.send(await getStuService()); }); module.exports = router;
Restful
在解釋 restful 之前,我們先來看一下 rest。
rest 的英語全稱為 Representational State Transfer,翻譯成中文是“表現層狀態轉移”。
其實這句話完整的說法是 resource representational state transfer,資源在表現層的狀態轉移。
-
資源:指的就是網路資源,或者說網路資料。網路上的一切東西都可以稱之為資源,例如一首歌,一部電影,一張圖片,一個圖示。網路上有這麼多資源,我們使用 URI 來標記。所謂上網,其實就是資源之間的互動。
-
representational state:表現層,指的是資源的一種表現形式。一段資料,我可與使用 json 來表示,也可以使用 xml 來表示。上面提到的 URI 只代表存在這個資源,但是這個資源的表現形式由表現層來定義。當我們請求一個數據的時候,響應頭裡面有一個欄位 content-type:html/text png/image jpeg/image
-
transfer:資源存續的狀態轉移。前面在學習 http 協議的時候,有 GET 請求、POST 請求,這些請求方式其實就是對一個資源進行操作
Restful 其實核心就是一點,應該使用不同的 HTTP 請求方式來標記資源狀態的改變。
HTTP 請求方式,實際上是有很多的:
-
GET
-
POST
-
DELETE
-
PUT
-
PATCH
-
....
使用 restful 設計 URL 前後的對比。
刪除一個評論:http://abc.com/?method=comment.del&id=xxx
或者
http://abc.com/comment/del/xxx
這樣設計 API 違背了 URI 的本質,URI 本質僅僅是標記網際網路上面的一個資源,不應該參雜任何的對該資源做出處理的行為
通過 Restful 的 URI 設計風格,可以還原 URI 的本質,讓 URI 僅僅是表示一個資源而已。
任何對該資源做的操作,都應該通過 HTTP 的請求方式來表示:
-
-
【新增】:【POST】http://abc.com/comment/1
-
【查詢】:【GET】http://abc.com/comment/1
-
【刪除】:【delete】http://abc.com/comment/1
-
【修改】:【PUT】http://abc.com/comment/1
-