Express
Express
- 介紹
- 安裝
搭建服務器的步驟
- express提供的新方法
- GET接口
- 獲取GET中的請求參數
- POST接口
- 獲取POST請求提交的數據
- 中間件原理
- 中間件語法
- 中間件初體驗(設置響應頭)
- 中間件開放靜態資源
- 中間件接收POST請求體
- 中間件返回404頁面
express 介紹
- Express 是一個第三方模塊,用于快速搭建服務器
- Express 是一個基于 Node.js 平臺,快速、開放、極簡的 web 開發框架。
- express保留了http模塊的基本API,使用express的時候,也能使用http的API
- express還額外封裝了一些新方法,能讓我們更方便的搭建服務器
- express提供了中間件功能,其他很多強大的第三方模塊都是基于express開發的
- Express 官網
- Express 中文文檔(非官方)
- Express GitHub倉庫
安裝express
項目文件夾中,執行 npm i express
。即可下載安裝express。
注意:express不能安裝在express文件夾中。否則安裝失敗。
使用Express構造Web服務器
使用Express構建Web服務器步驟:
-
加載 express 模塊
-
創建 express 服務器
-
開啟服務器
-
監聽瀏覽器請求并進行處理
// 使用express 搭建web服務器
// 1) 加載 express 模塊
const express = require('express');// 2) 創建 express 服務器
const app = express();// 3) 開啟服務器
app.listen(3006, () => console.log('express服務器開始工作了'));// 4) 監聽瀏覽器請求并進行處理app.get('GET請求的地址', 處理函數);app.post('POST請求的地址', 處理函數);
express封裝的新方法
express之所以能夠實現web服務器的搭建,是因為其內部對核心模塊http進行了封裝。
封裝之后,express提供了非常方便好用的方法。
-
express
- express.static() – 開放靜態資源
- express.urlencoded() – 獲取POST請求體
- 其他…
-
app
app.get()
– 處理客戶端的GET請求app.post()
– 處理客戶端的POST請求- app.use() – 設置應用級別的中間件
- 其他…
-
req
- req.body – 獲取POST請求體
- req.params – 獲取GET請求動態參數
- req.query – 獲取GET請求參數(獲取查詢字符串參數)
- 其他…
-
res
res.sendFile(文件的絕對路徑)
– 讀取文件,并將結果響應res.set({name, value})
– 設置響應頭res.status(200)
– 設置響應狀態碼res.send(字符串或對象)
– 響應結果res.json(對象)
– 以JSON格式響應結果- res.jsonp() – 以JSONP格式響應結果
- 其他…
請注意,在express中,我們仍然可以使用http模塊中的方法。
GET接口
// app.get('請求的URL', callback);
app.get('/api/getbooks', (req, res) => {// 處理GET方式的/api/getbooks接口
});app.get('/', (req, res) => {// 客戶端沒有指定請求的url,在這里處理。
});app.get('*', (req, res) => {// 處理所有的GET請求
})
app.get('*', (req, res) => {})
他能夠匹配到所有的GET請求,所以把它放到所有接口的最后。
獲取GET方式請求的參數
獲取url?參數=值&參數=值
- 這種方式的參數,比較常規,參數部分也叫做查詢字符串
- 請求地址的寫法: http://localhost:3006/test?id=3&bookname=zxx&age=20
- 獲取方式:
req.query
// 寫接口
app.get('/test', (req, res) => {console.log(req.query); // { id: '3', bookname: 'zxx', age: '20' }});
獲取 url/:id/:name/:age
- 這種方式的參數,叫做動態參數
- 請求地址的寫法:http://localhost:3006/test/3/zs/30
- 要求請求的url參數必填,否則不能和定義的接口匹配
// 1個參數
// 瀏覽器的請求 http://localhost/test/3
// 測試接口,獲取動態參數
app.get('/test/:id', (req, res) => {console.log(req.params); // 可以獲取所有的動態參數 { id: 3 }res.send('收到參數');
});// 多個參數
// 瀏覽器的請求 http://localhost/test2/3/zhangsan/20
// 測試接口,獲取多個動態參數
app.get('/test2/:id/:name/:age', (req, res) => {console.log(req.params); // 可以獲取所有的動態參數 // { id: '4', name: 'zhangsan', age: '20' }res.send('全部收到');
});
POST接口
// app.post('請求的URL', callback);
app.post('/api/addbook', (req, res) => {// 處理POST方式的/api/addbook接口
});app.post('*', (req, res) => {// 處理所有的POST請求
})
獲取POST請求體
-
GET方式沒有請求體,POST方式才有請求體。
-
請求體,即客戶端提交的數據。
-
我們仍然可以使用http模塊中的語法,獲取請求體。
-
POST請求體,有哪些格式
- 查詢字符串 – 對應的
Content-Type: application/x-www-form-urlencoded
- FormData對象 – 對應的
Content-Type: multipart/form-data; --XXADFsdfssf
- 查詢字符串 – 對應的
請求體是查詢字符串
// 客戶端,需要發送POST請求,提交的數據隨便寫// 寫接口之前,配置
// 可以幫我們接收 content-type: application/x-www-form-urlencoded類型的請求體
app.use(express.urlencoded({extended: false}));// 后續,任何一個POST接口,都可以通過req.body獲取到請求體的內容
app.post('/test', (req, res) => {// 獲取請求體console.log(req.body);res.send('你的請求體收到了');
});
postman發送一個POST方式的請求,來配合測試:
獲取FormData類型的請求體
比較麻煩,需要使用第三方模塊(multer)才能夠獲取到。這里不做演示。
中間件介紹
-
中間件(Middleware ),特指業務流程的中間處理環節。
-
中間件,是express最大的特色,也是最重要的一個設計
-
很多第三方模塊,都可以當做express的中間件,配合express,開發更簡單。
-
一個express應用,是由各種各樣的中間件組合完成的
-
中間件,本質上就是一個 函數/方法
中間件原理
為了理解中間件,我們先來看一下我們現實生活中的自來水廠的凈水流程。
- 在上圖中,自來水廠從獲取水源到凈化處理交給用戶,中間經歷了一系列的處理環節
- 我們稱其中的每一個處理環節就是一個中間件。
- 這樣做的目的既提高了生產效率也保證了可維護性。
express中間件原理:
中間件語法
-
中間件就是一個函數
-
中間件函數中有四個基本參數, err、req、res、next
- 很多情況下,err都會省略
- req就是請求相關的對象
- res就是響應相關的對象
- next:它是一個函數,某些時候,可以省略
-
把寫好的中間件函數,傳遞給
app.get()
、app.post()``或app.use()
使用
示例代碼:
// app.get('/api/getbooks', 中間件函數);
app.get('/api/getbooks', (req, res) => {})app.post('/api/add', 中間件函數, 中間件函數, 中間件函數, ......);// app.use([path], 中間件函數);
app.use((req, res, next) => {});app.use('/my', (req, res, next) => {});
中間件的特點
- 每個中間件函數,共享req對象、共享res對象
- js代碼中,所有的req對象是一個對象;所有的res是一個對象
- 不調用
next()
,則程序執行到當前中間件函數后,不再向后執行- 注意中間件的順序,因為有可能因為順序原因,你的中間件函數不會執行
- 為了防止代碼邏輯混亂,調用 next() 函數后不要再寫額外的代碼
- 客戶端發送過來的請求,可能連續調用多個中間件進行處理
- 使用
app.use()
注冊的中間件,GET和POST請求都可以觸發
中間件初體驗
為所有的請求,統一設置響應頭
// 圖書管理案例中,為所有的接口解決跨域問題
// 自定義中間件函數,統一處理跨域
app.use((req, res, next) => {// 為后續所有的接口設置響應頭,解決跨域問題res.set({'Access-Control-Allow-Origin': '*'});next();
});
中間件詳細使用方法
app.use的第一個參數
// 匹配url開頭是 /my 的接口,比如 /my/aa /my/bb ,但是不能匹配 /mynadsf
app.use('/my', (req, res, next) => {req.abc = '123';next();
});// 匹配url的開頭是 /my 的接口,比如 /my/aa /my/bb /mysadfa /myasdfdd
app.use('/my*', (req, res, next) => {.....
});
app.get 和 app.post使用多個中間件
//
// app.get('/abcd', ()=>{}, ()=>{}, ()=>{}, ....);app.get('/abcd', (req, res, next) => {req.abc = 'a';next();
}, (req, res, next) => {req.abc += 'b';next();
}, (req, res) => {res.send(req.abc);
});// app.get('/abcd', [()=>{}, ()=>{}, ....], ()=>{});
let a = (req, res, next) => {req.abc = 'a';next();
};let b = (req, res, next) => {req.abc += 'b';next();
}app.get('/abcd', [a, b], (req, res) => {res.send(req.abc);
});
中間件的分類
- 應用級別中間件
- 針對整個項目進行配置的中間件,叫做應用級別的中間件
- 路由級別中間件
- 寫到路由文件中的中間件(稍后介紹路由)
- 錯誤處理中間件
- 一般一個項目在最后,設置一個錯誤處理中間件即可。
- 錯誤處理中間件,需要填4個參數(err, req, res, next)
- 內置中間件
- express自帶的中間件
express.urlencoded()
express.static()
- express自帶的中間件
- 第三方中間件
- 別人寫的模塊,發布到npm上,我們下載下來,可以當做express的中間件
- multer – 接收FormData數據的模塊
cors
- 解決跨域的- …
- 別人寫的模塊,發布到npm上,我們下載下來,可以當做express的中間件
回顧獲取請求體的方法
統一獲取post請求體
app.use(express.urlencoded({extended: false}));
// app.use(方法); --- 這是在配置中間件
// express.urlencoded() --- 它是中間件函數,是express內置的中間件
// https://www.expressjs.com.cn/4x/api.html#express.urlencoded
express.urlencoded() 這也是一個函數,而且也是一個中間件函數。
它內部實現的原理是:
app.use((req, res, next) => {if (req.method === 'POST') {var str = '';req.on('data', chunk => {str += chunk;});req.on('end', () => {const querystring = require('querystring')req.body = querystring.parse(str);next();})} else {next();}
});
很多中間件,別人早已經寫好了。我們直接使用即可。
我們后面還會做很多事情,比如開放靜態資源、實現跨域資源共享(CORS)、身份認證、圖片上傳等等工作,別人早已經寫好中間件了。我們后面學習這些中間件如何使用即可。
中間件開放靜態資源
- 什么叫做靜態資源
- css文件
- 圖片文件
- js文件
- 有時候也包括html文件
- 等等
- 什么叫做開放靜態資源
- 開放,即允許客戶端來訪問
- 具體做法
- 比如,允許客戶端訪問public文件夾里面的文件
app.use(express.static('public'))
中間件接收POST請求體
-
POST請求體的類型(Content-Type)
- application/x-www-form-urlencoded 比如:id=1&name=zs&age=20
- form-data 比如,提交的是FormData對象
- application/json 比如,提交的是 {“id”: 1, “name”: “zs”, “age”: 20}
- 其他…
-
服務器端接收不同類型的請求體,使用的方式是不同的
- urlencoded —>
app.use(express.urlencoded({extended: false}));
- application/json —>
app.use(express.json());
– 沒有演示 - form-data —> 服務器端使用第三方模塊處理(
multer
)
- urlencoded —>
當初學習ajax的時候,如果是POST請求,為什么要加Content-Type
使用第三方的中間件,實現跨域資源共享
昨天,我們自己寫了中間件,實現了跨域資源共享(CORS)。但是是自己寫的中間件。
實際上,實現跨域資源共享,可以使用一個叫做 cors 的第三方模塊。推薦使用它來實現跨域資源共享。
使用方法:
- 下載安裝cors
npm i cors
const cors = require('cors');
— 加載模塊app.use(cors());
– 注冊中間件即可
中間件返回404頁面
- 服務器的代碼,你的接口要寫到前面
- 當瀏覽器的請求到達服務器,優先使用你的接口
- 如果請求的不是你的接口,則返回404頁面
- 所以,處理404要放到代碼的最后。