基于Node.js平臺的Express教程
- Express 簡介
- 什么是 Express
- Express 能做什么
- Express 的基本使用
- 安裝 Express
- 創建基本的 Web 服務器
- 監聽 GET 請求
- 監聽 POST 請求
- 獲取 URL 中攜帶的查詢引數
- 獲取 URL 中的動態引數
- 托管靜態資源
- express.static()
- 托管多個靜態資源目錄
- 掛載路徑前綴
- nodemon
- nodemon 的作用
- 安裝 nodemon
- 使用 nodemon
- Express 路由
- 路由的概念
- Express 中的路由
- 路由的匹配程序
- 路由的使用
- 簡單用法
- 模塊化路由
- 創建路由模塊
- 注冊路由模塊
- 為路由模塊添加前綴
- Express 中間件
- 中間件的概念
- 什么是中間件
- Express 中間件的呼叫流程
- Express 中間件的格式
- next 函式的作用
- Express 中間件的使用案例
- 定義中間件函式
- 全域生效的中間件
- 中間件的作用
- 定義多個全域中間件
- 區域生效的中間件
- 定義多個區域中間件
- 使用注意事項
- 中間件的分類
- 應用級別的中間件
- 路由級別的中間件
- 錯誤級別中間件
- 第三方的中間件
- Express 寫介面
- 開發程序檔案結構推薦
Express 簡介
什么是 Express
官方的概念:Express 是基于 Node.js 平臺,快速、開放、極簡的 Web 開發框架,
Express 的本質:就是一個 npm 上的第三方包,提供了快速創建 Web 服務器的便捷方法,
使用 Express 框架的原因:
http 內置模塊用起來很復雜,開發效率低;Express 是基于內置的 http 模塊進一步封裝出來的,能夠極大的提高開發效率,
Express 能做什么
最常見的兩種服務器,分別是:
-
Web 網站服務器:專門對外提供 Web 網頁資源的服務器,
-
API 介面服務器:專門對外提供 API 介面的服務器,
使用 Express,可以方便、快速的創建 Web 網站的服務器或 API 介面的服務器,
Express 的基本使用
安裝 Express
在專案所處的目錄中,運行如下的終端命令,即可將 express 安裝到專案中使用:
npm i express
創建基本的 Web 服務器
// 1. 匯入 express
const express = require('express')
// 2. 創建 web 服務器
const app = express()
// 3. 啟動 web 服務器
app.listen(80, () => {
console.log('express server running at http://127.0.0.1')
})
其中開啟的是默認主機IP為:127.0.0.1
80埠也是默認埠,也可以輸入其他數字開啟其他埠
開啟服務需要此檔案所在目錄下打開終端,輸入下面命令:
node app.js
其中 app.js 為你所命名的檔案名,
監聽 GET 請求
通過 app.get() 方法,可以監聽客戶端的 GET 請求,具體的語法格式如下:
app.get('/user', (req, res) => {
// 呼叫 express 提供的 res.send() 方法,向客戶端回應一個 JSON 物件
res.send({ name: 'zs', age: 20, gender: '男' })
})
監聽 POST 請求
通過 app.post() 方法,可以監聽客戶端的 POST 請求,具體的語法格式如下:
app.post('/user', (req, res) => {
// 呼叫 express 提供的 res.send() 方法,向客戶端回應一個 文本字串
res.send('請求成功!')
})
獲取 URL 中攜帶的查詢引數
通過 req.query 物件,可以訪問到客戶端通過查詢字串的形式,發送到服務器的引數:
app.get('/', (req, res) => {
// 通過 req.query 可以獲取到客戶端發送過來的 查詢引數
// 注意:默認情況下,req.query 是一個空物件
console.log(req.query)
res.send(req.query)
})
// 客戶端發送 ?name=zs&age=20
// req.query.name req.query.age獲取
獲取 URL 中的動態引數
通過 req.params 物件,可以訪問到 URL 中,通過 : 匹配到的動態引數:
// 注意:這里的 :ids 是一個動態的引數,命名可以任意的, 通過 / 來分割多個引數
app.get('/user/:ids/:username', (req, res) => {
// req.params 是動態匹配到的 URL 引數,默認也是一個空物件
console.log(req.params)
res.send(req.params)
})
// 服務端輸入http://127.0.0.1/1/zs
// 會動態匹配 {ids = 1,username = zs}
托管靜態資源
express.static()
express.static(),通過它,我們可以創建一個靜態資源服務器,
例如,通過如下代碼就可以將 app 目錄下的HTML、圖片、CSS 檔案、JavaScript 檔案對外開放訪問了:
app.use(express.static('./app'))
現在,你就可以訪問 public 目錄中的所有檔案了:
http://localhost:80/index.html
http://localhost:80/images/bg.jpg
http://localhost:80/css/index.css
http://localhost:80/js/indxe.js
注意:Express 在指定的靜態目錄中查找檔案,并對外提供資源的訪問路徑,因此,存放靜態檔案的目錄名不會出現在 URL 中,即 app 這個目錄名不會出現在 URL 中,
托管多個靜態資源目錄
如果要托管多個靜態資源目錄,可以多次呼叫 express.static() 函式:
// 在這里,呼叫 express.static() 方法,快速的對外提供靜態資源
app.use(express.static('./files'))
app.use(express.static('./app'))
訪問靜態資源檔案時,express.static() 函式會根據目錄的添加順序查找所需的檔案,遇到同名目錄時安添加靜態資源的順序加載,
掛載路徑前綴
如果希望在托管的靜態資源訪問路徑之前,掛載路徑前綴,則可以使用如下的方式:
app.use('/app', express.static('./app'))
現在,你就可以通過帶有 /app 前綴地址來訪問 app 目錄中的檔案了:
http://localhost:80/app/index.html
http://localhost:80/app/images/bg.jpg
http://localhost:80/app/css/index.css
http://localhost:80/app/js/indxe.js
nodemon
nodemon 的作用
在撰寫除錯 Node.js 專案的時候,如果修改了專案的代碼,則需要頻繁的手動關掉,然后再重新啟動,這樣的操作過于繁瑣,
nodemon ,它能夠監聽專案檔案的變動,當代碼被修改后,nodemon 會自動幫我們重啟專案,極大方便了開發和除錯,
nodemon模塊檔案鏈接
安裝 nodemon
在終端中,運行如下命令,即可將 nodemon 安裝為全域可用的工具:
npm install -g nodemon
建議安裝在全域的環境中,在其他專案也可以使用這個這個模塊,
使用 nodemon
和之前啟動服務器的方法相同,只是開始的命令不同,將 node 換成 nodemon
nodemon app.js
Express 路由
路由的概念
廣義上來講,路由就是映射關系,
Express 中的路由
在 Express 中,路由指的是客戶端的請求與服務器處理函式之間的映射關系,
Express 中的路由分 3 部分組成,分別是請求的型別、請求的 URL 地址、處理函式,格式如下:(這個只是格式,不是具體命令)
app.METHOD(PATH, HANDLER)
METHOD 代表具體客戶端請求,比如 GET 、 POST ;
PATH 代表請求的 URL 地址;
HANDLER 代表處理函式;
路由的匹配程序
每當一個請求到達服務器之后,需要先經過路由的匹配,只有匹配成功之后,才會呼叫對應的處理函式,
在匹配時,會按照路由的順序進行匹配,如果請求型別和請求的 URL 同時匹配成功,則 Express 會將這次請求,轉交給對應的 function 函式進行處理,

路由匹配的注意點:
① 按照定義的先后順序進行匹配
② 請求型別和請求的URL同時匹配成功,才會呼叫對應的處理函式
路由的使用
簡單用法
把路由掛載到 app 上,示例代碼如下:
const express = require('express')
const app = express()
// 掛載路由
app.get('/user', (req, res) => {
res.send('hello world.')
})
app.post('/login', (req, res) => {
res.send('Post Request.')
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
開啟服務器后,瀏覽器中輸入 http://127.0.0.1/user 可以獲取到 hello world.
模塊化路由
為了方便對路由進行模塊化的管理,不建議將路由直接掛載到 app 上,而是推薦將路由抽離為單獨的模塊,
將路由抽離為單獨模塊的步驟如下:
-
創建路由模塊對應的 router.js 檔案
-
呼叫 express.Router() 函式創建路由物件
-
向路由物件上掛載具體的路由
-
使用 module.exports 向外共享路由物件
-
在 app.js 檔案中使用 app.use() 函式注冊路由模塊
創建路由模塊
router.js
使用 router 命名只是為了易于理解,實際開發中,不一定要用 router 命名,
// 這是路由模塊
// 1. 匯入 express
const express = require('express')
// 2. 創建路由物件
const router = express.Router()
// 3. 掛載具體的路由
router.get('/user/list', (req, res) => {
res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
res.send('Add new user.')
})
// 4. 向外匯出路由物件
module.exports = router
注冊路由模塊
app.js
const express = require('express')
const app = express()
// 1. 匯入路由模塊
const router = require('./router')
// 2. 注冊路由模塊
app.use(router)
app.listen(80, () => {
console.log('http://127.0.0.1')
})
注意: app.use() 函式的作用,就是來注冊全域中間件,有關中間件內容,下面文章會介紹,
為路由模塊添加前綴
類似于托管靜態資源時,為靜態資源統一掛載訪問前綴方式一樣:
app.use('/api', router)
使用 app.ues( ) 注冊路由模塊,并添加統一的訪問前綴 /API
比如:在上面步驟中所創建的 router.js 檔案里面所撰寫的請求中,在沒有為路由模塊添加前綴前,呼叫介面的 URL 地址是:http://127.0.0.1/user/list
而為路由模塊添加前綴后,呼叫介面的 URL 地址是:
http://127.0.0.1/api/user/list
Express 中間件
中間件的概念
什么是中間件
中間件特指業務流程的中間處理環節,
Express 中間件的呼叫流程
當一個請求到達 Express 的服務器之后,可以連續呼叫多個中間件,從而對這次請求進行預處理,

Express 中間件的格式
Express 的中間件,本質上就是一個 function 處理函式,Express 中間件的格式如下:
app.get('/', function(req, res, next){
next();
})
注意:
中間件函式的形參串列中,必須包含 next 引數,
而路由處理函式中只包含 req 和 res,
next 函式的作用
next 函式是實作多個中間件連續呼叫的關鍵,它表示把流轉關系轉交給下一個中間件或路由,

Express 中間件的使用案例
定義中間件函式
可以通過如下的方式,定義一個中間件函式:
// 定義一個最簡單的中間件函式
const mw = function (req, res, next) {
console.log('這是中間件函式')
// 把流轉關系,轉交給下一個中間件或路由
next()
}
全域生效的中間件
客戶端發起的任何請求,到達服務器之后,都會觸發的中間件,叫做全域生效的中間件,
通過呼叫 app.use(中間件函式),即可定義一個全域生效的中間件,示例代碼如下:
const express = require('express')
const app = express()
// 這是定義全域中間件的簡化形式
app.use((req, res, next) => {
console.log('這是中間件函式')
next()
})
app.get('/', (req, res) => {
console.log('呼叫了 / 這個路由')
res.send('Home page.')
})
app.get('/user', (req, res) => {
console.log('呼叫了 /user 這個路由')
res.send('User page.')
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
中間件的作用
多個中間件之間,共享同一份 req 和 res,基于這樣的特性,我們可以在上游的中間件中,統一為 req 或 res 物件添加自定義的屬性或方法,供下游的中間件或路由進行使用,
const express = require('express')
const app = express()
// 這是定義全域中間件的簡化形式
app.use((req, res, next) => {
// 獲取到請求到達服務器的時間
const time = Date.now()
// 為 req 物件,掛載自定義屬性,從而把時間共享給后面的所有路由
req.startTime = time
next()
})
app.get('/', (req, res) => {
res.send('Home page.' + req.startTime)
})
app.get('/user', (req, res) => {
res.send('User page.' + req.startTime)
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
定義多個全域中間件
可以使用 app.use() 連續定義多個全域中間件,客戶端請求到達服務器之后,會按照中間件定義的先后順序依次進行呼叫,示例代碼如下:
const express = require('express')
const app = express()
// 定義第一個全域中間件
app.use((req, res, next) => {
console.log('呼叫了第1個全域中間件')
next()
})
// 定義第二個全域中間件
app.use((req, res, next) => {
console.log('呼叫了第2個全域中間件')
next()
})
// 定義一個路由
app.get('/user', (req, res) => {
res.send('User page.')
})
app.listen(80, () => {
console.log('http://127.0.0.1')
})
區域生效的中間件
不使用 app.use() 定義的中間件,叫做區域生效的中間件,示例代碼如下:
// 匯入 express 模塊
const express = require('express')
// 創建 express 的服務器實體
const app = express()
// 1. 定義中間件函式
const mw = (req, res, next) => {
console.log('呼叫了區域生效的中間件')
next()
}
// 2. 創建路由
app.get('/', mw, (req, res) => {
res.send('Home page.')
})
app.get('/user', (req, res) => {
res.send('User page.')
})
// 呼叫 app.listen 方法,指定埠號并啟動web服務器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
定義多個區域中間件
可以在路由中,通過如下兩種等價的方式,使用多個區域中間件:
app.get('/', mw1, mw2, (req, res) => {
res.send('Home page.')
})
app.get('/', [mw1, mw2], (req, res) => {
res.send('Home page.')
})
// 匯入 express 模塊
const express = require('express')
// 創建 express 的服務器實體
const app = express()
// 1. 定義中間件函式
const mw1 = (req, res, next) => {
console.log('呼叫了第一個區域生效的中間件')
next()
}
const mw2 = (req, res, next) => {
console.log('呼叫了第二個區域生效的中間件')
next()
}
// 2. 創建路由
app.get('/', [mw1, mw2], (req, res) => {
res.send('Home page.')
})
app.get('/user', (req, res) => {
res.send('User page.')
})
// 呼叫 app.listen 方法,指定埠號并啟動web服務器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
使用注意事項
-
一定要在路由之前注冊中間件
-
客戶端發送過來的請求,可以連續呼叫多個中間件進行處理
-
執行完中間件的業務代碼之后,不要忘記呼叫 next() 函式
-
為了防止代碼邏輯混亂,呼叫 next() 函式后不要再寫額外的代碼
-
連續呼叫多個中間件時,多個中間件之間,共享 req 和 res 物件
-
在中間件不可以發送多個回應,否則會報錯,
中間件的分類
Express 官方把常見的中間件用法,分成了 5 大類,分別是:
-
應用級別的中間件
-
路由級別的中間件
-
錯誤級別的中間件
-
Express 內置的中間件
-
第三方的中間件
應用級別的中間件
通過 app.use() 或 app.get() 或 app.post() ,系結到 app 實體上的中間件,叫做應用級別的中間件,代碼示例如下:
// 應用級別的中間件,全域中間件
app.use((req, res, next) => {
next()
})
// 應用級別的中間件,區域中間件
app.get('/', mw1, (req, res) => {
res.send()
})
路由級別的中間件
系結到 express.Router() 實體上的中間件,叫做路由級別的中間件,它的用法和應用級別中間件沒有任何區別,只不過,應用級別中間件是系結到 app 實體上,路由級別中間件系結到 router 實體上,代碼示例如下:
var app = express()
var router = express.Router()
// 路由級別的中間件
router.use((req, res, next) => {
next()
})
app.use('/', router)
錯誤級別中間件
錯誤級別中間件的作用:專門用來捕獲整個專案中發生的例外錯誤,從而防止專案例外崩潰的問題,
格式:錯誤級別中間件的 function 處理函式中,必須有 4 個形參,形參順序從前到后,分別是 (err, req, res, next),
// 匯入 express 模塊
const express = require('express')
// 創建 express 的服務器實體
const app = express()
// 1. 定義路由
app.get('/', (req, res) => {
// 人為的制造錯誤
throw new Error('服務器內部發生了錯誤!')
res.send('Home page.')
})
// 2. 定義錯誤級別的中間件,捕獲整個專案的例外錯誤,從而防止服務器程式的崩潰
app.use((err, req, res, next) => {
console.log('發生了錯誤!' + err.message)
res.send('Error:' + err.message)
})
// 呼叫 app.listen 方法,指定埠號并啟動web服務器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
**注意:**錯誤級別的中間件,必須注冊在所有路由之后!
自 Express 4.16.0 版本開始,Express 內置了 3 個常用的中間件:
-
express.static 快速托管靜態資源的內置中間件,例如: HTML 檔案、圖片、CSS 樣式等(無兼容性)
-
express.json 決議 JSON 格式的請求體資料(有兼容性,僅在 4.16.0+ 版本中可用)
-
express.urlencoded 決議 URL-encoded 格式的請求體資料(有兼容性,僅在 4.16.0+ 版本中可用)
// 匯入 express 模塊
const express = require('express')
// 創建 express 的服務器實體
const app = express()
// 注意:除了錯誤級別的中間件,其他的中間件,必須在路由之前進行配置
// 通過 express.json() 這個中間件,決議表單中的 JSON 格式的資料
app.use(express.json())
// 通過 express.urlencoded() 這個中間件,來決議 表單中的 url-encoded 格式的資料
app.use(express.urlencoded({ extended: false }))
app.post('/user', (req, res) => {
// 在服務器,可以使用 req.body 這個屬性,來接收客戶端發送過來的請求體資料
// 默認情況下,如果不配置決議表單資料的中間件,則 req.body 默認等于 undefined
console.log(req.body)
res.send('ok')
})
app.post('/book', (req, res) => {
// 在服務器端,可以通過 req,body 來獲取 JSON 格式的表單資料和 url-encoded 格式的資料
console.log(req.body)
res.send('ok')
})
// 呼叫 app.listen 方法,指定埠號并啟動web服務器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
第三方的中間件
非 Express 官方內置的,而是由第三方開發出來的中間件,叫做第三方中間件,在專案中,大家可以按需下載并配置第三方中間件,從而提高專案的開發效率,
例如:在 express@4.16.0 之前的版本中,經常使用 body-parser 這個第三方中間件,來決議請求體資料,使用步驟如下:
-
運行 npm install body-parser 安裝中間件
-
使用 require 匯入中間件
-
呼叫 app.use() 注冊并使用中間件
注意:Express 內置的 express.urlencoded 中間件,就是基于 body-parser 這個第三方中間件進一步封裝出來的,現在好像是不建議使用body-parser ,而是使用 express.urlencoded
// 匯入 express 模塊
const express = require('express')
// 創建 express 的服務器實體
const app = express()
// 1. 匯入決議表單資料的中間件 body-parser
const parser = require('body-parser')
// 2. 使用 app.use() 注冊中間件
app.use(parser.urlencoded({ extended: false }))
// app.use(express.urlencoded({ extended: false }))
app.post('/user', (req, res) => {
// 如果沒有配置任何決議表單資料的中間件,則 req.body 默認等于 undefined
console.log(req.body)
res.send('ok')
})
// 呼叫 app.listen 方法,指定埠號并啟動web服務器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})
Express 寫介面
router.get('/uesr', (req, res) => {
// 處理程序
res.send({
status: 200,
msg: '請求成功!',
data: data // 資料
})
})
開發程序檔案結構推薦

其中
router目錄 是路由級別中間件
router_handle目錄 是路由級別中間件處理函式
app.js 檔案 是應用級別中間件
有關更多檔案結構的內容將在下一遍文章介紹,敬請期待~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/272898.html
標籤:其他
上一篇:css定位體系(2)
