《Express:Node.js 里的 “閃電俠”》

?“你就坐在我身邊,好不好”


什么是Express

官方給出的概念:Express 是基于 Node.js 平臺,快速、開放、極簡的 Web 開發框架。

通俗的理解:Express 的作用和 Node.js 內置的 http 模塊類似,是專門用來創建 Web 服務器的

Express的本質:就是一個npm上的第三方包,提供了快速創建Web服務器的便捷方法。?

為什么要有Express

?http 內置模塊用起來很復雜,開發效率低;Express 是基于內置的 http 模塊進一步封裝出來的,能夠極大的提高開發效率。

Express和http的關系

類似于瀏覽器中 Web API 和 jQuery 的關系。前者是基于后者進一步封裝出來的。

Express能做什么

對于前端程序員來說,最常見的兩種服務器,分別是:

  • Web 網站服務器:專門對外提供 Web 網頁資源的服務器。
  • API 接口服務器:專門對外提供 API 接口的服務器。

使用 Express,我們可以方便、快速的創建 Web 網站的服務器或 API 接口的服務器。

Express的基本使用

安裝

在項目所處的目錄中,運行如下的終端命令,即可將 express 安裝到項目中使用:

npm i express

?創建基本的Web服務器

//導入express
const express=require('express')
//創建web服務器
const app=express()
//調用app.listen(端口號,啟動成功后的回調函數),啟動服務器
app.listen(80,()=>{
console.log('express server running at http://127.0.0.1')
})

監聽GET請求

通過app.get()方法,可以監聽客戶端的GET請求,具體請求語法如下:

//參數1:客戶端請求的URL地址
//參數2:請求對應的處理函數
//req:請求對象(包含了與請求相關的屬性和方法)
//res:響應對象(包含了與響應相關的屬性與方法)app.get('請求URL',function(req,res){
/*處理函數*/})

監聽POST請求

通過 app.post() 方法,可以監聽客戶端的 POST 請求,具體的語法格式如下:

//參數1:客戶端請求的URL地址
//參數2:請求對應的處理函數
//req:請求對象(包含了與請求相關的屬性和方法)
//res:響應對象(包含了與響應相關的屬性與方法)app.post('請求URL',function(req,res){
/*處理函數*/})

把內容響應給客戶端

通過 res.send() 方法,可以把處理好的內容,發送給客戶端:

app.get('/user',(req,res)=>{
//向客戶端發送JSON對象
res.send({name:'Camellia',age:19,gender:'女'{)
{)app.post('/user',(req,res)=>{
//向客戶端發送文本內容
res.send('請求成功‘)
})

獲取 URL 中攜帶的查詢參數

通過 req.query 對象,可以訪問到客戶端通過查詢字符串的形式,發送到服務器的參數:

app.get('/',(req,res)=>{
//req.query默認是一個空對象
//客戶端使用?name=Camellia&age=19 這種查詢字符串形式,發送到服務器的參數,
//可以通過req.query對象訪問到,例如:
//req.query.name    req.query.qge
console.log(req.query)
})

獲取 URL 中的動態參數

通過 req.params 對象,可以訪問到 URL 中,通過 : 匹配到的動態參數:

//URL地址中,可以通過 :參數名 的形式,匹配動態參數值
app.get('/user/:id',(req,res)=>{
//req.params 默認是一個空對象
//里面存放著通過 :動態匹配到的值
console.log(req.params)
})

托管靜態資源

express.static()

express 提供了一個非常好用的函數,叫做 express.static(),通過它,我們可以非常方便地創建一個靜態資源服務器, 例如,通過如下代碼就可以將 public 目錄下的圖片、CSS 文件、JavaScript 文件對外開放訪問了:

app.use(express.static('public'))

現在,你就可以訪問 public 目錄中的所有文件了:

  • http://localhost:3000/images/bg.jpg
  • http://localhost:3000/css/style.css
  • http://localhost:3000/js/login.js

Express 在指定的靜態目錄中查找文件,并對外提供資源的訪問路徑。 因此,存放靜態文件的目錄名不會出現在 URL 中。

托管多個靜態資源目錄

如果要托管多個靜態資源目錄,請多次調用 express.static() 函數:

app.use(express.satic('public'))
app/use(express.static('files'))

訪問靜態資源文件時,express.static() 函數會根據目錄的添加順序查找所需的文件。?

掛載路徑前綴

如果希望在托管的靜態資源訪問路徑之前,掛載路徑前綴,則可以使用如下的方式:

app.use('/public',express.static('/public'))

現在,你就可以通過帶有 /public 前綴地址來訪問 public 目錄中的文件了:

  • http://localhost:3000/public/images/kitten.jpg
  • http://localhost:3000/public/css/style.css
  • http://localhost:3000/public/js/app.js

nodemon

為什么要使用 nodemon

在編寫調試 Node.js 項目的時候,如果修改了項目的代碼,則需要頻繁的手動 close 掉,然后再重新啟動,非常繁瑣。 現在,我們可以使用 nodemo(https://www.npmjs.com/package/nodemon) 這個工具,它能夠監聽項目文件 的變動,當代碼被修改后,nodemon 會自動幫我們重啟項目,極大方便了開發和調試。

安裝 nodemon

在終端中,運行如下命令,即可將 nodemon 安裝為全局可用的工具:

npm i -g nodemon

使用 nodemon

當基于 Node.js 編寫了一個網站應用的時候,傳統的方式,是運行 node app.js 命令,來啟動項目。這樣做的壞處是: 代碼被修改之后,需要手動重啟項目。

現在,我們可以將 node 命令替換為 nodemon 命令,使用 nodemon app.js 來啟動項目。這樣做的好處是:代碼 被修改之后,會被 nodemon 監聽到,從而實現自動重啟項目的效果。

Express路由

在 Express 中,路由指的是客戶端的請求與服務器處理函數之間的映射關系。 Express 中的路由分 3 部分組成,分別是請求的類型、請求的 URL 地址、處理函數,格式如下:

app.METHOD(PATH,HANDLER)

Express 中的路由的例子

//陪陪GET請求,且請求URL為/
app.get('/',function(req,res){
res.send('hello Camellia')
})
//匹配POST請求,且請求URL為/
app.post('/',function (req,res){
res.send('Got a POSR request')
})

路由的匹配過程

每當一個請求到達服務器之后,需要先經過路由的匹配,只有匹配成功之后,才會調用對應的處理函數。

在匹配時,會按照路由的順序進行匹配,如果請求類型請求的 URL 同時匹配成功,則 Express 會將這次請求,轉 交給對應的 function 函數進行處理。

?路由的使用

最簡單的用法

在 Express 中使用路由最簡單的方式,就是把路由掛載到 app 上,示例代碼如下:

const express=rquire('express')
//創建Web服務器,命名為app
const app=express()
//掛載路由
app.get('/',(req,res)=>{
res.send('hello camellia')})
app.post('/',(req,res)=>{
res.send('POST request')})
//啟動Web服務器
app/listen(80,()=>{console.log('server running at http://127.0.0.1')})

模塊化路由

為了方便對路由進行模塊化的管理,Express 不建議將路由直接掛載到 app 上,而是推薦將路由抽離為單獨的模塊。 將路由抽離為單獨模塊的步驟如下:

  • ①創建路由模塊對應的 .js 文件
  • ② 調用 express.Router() 函數創建路由對象
  • ③ 向路由對象上掛載具體的路由
  • ④ 使用 module.exports 向外共享路由對象
  • ⑤ 使用 app.use() 函數注冊路由模塊

創建路由模塊

//導入express
var express =require('express')
//創建路由對象
var router =express.Router()
//掛載獲取用戶列表的路由
router.get('/user/list',function(req,res){
res.send('Get user list.')
//掛載添加用戶的路由
router.post('/user/add',function(req,res){
res.send('Add new user.')
//向外導出路由對象
module.exports=router

注冊路由模塊

//導入路由模塊
const userRouter=require('./router/user.js')
//使用app.use()注冊路由模塊
app/use(useRouter)

為路由模塊添加前綴

類似于托管靜態資源時,為靜態資源統一掛載訪問前綴一樣,路由模塊添加前綴的方式也非常簡單:

//導入路由模塊
const userRouter=require('./router/user.js')
//使用app.use()注冊路由模塊,并添加統一的訪問前綴/apiapp.use('/api',userRouter)

Express中間件

中間件(Middleware ),特指業務流程的中間處理環節。

Express 中間件的調用流程

當一個請求到達 Express 的服務器之后,可以連續調用多個中間件,從而對這次請求進行預處理。

Express 中間件的格式

?Express 的中間件,本質上就是一個 function 處理函數,Express 中間件的格式如下:

?

注意:中間件函數的形參列表中,必須包含 next 參數。而路由處理函數中只包含 req 和 res。?

next 函數的作用

?next 函數是實現多個中間件連續調用的關鍵,它表示把流轉關系轉交給下一個中間件或路由。

?

Express中間件的初步體驗

?定義中間件函數

可以通過如下的方式,定義一個最簡單的中間件函數:

const mw=function(req,res,next){
console.log('這是要最簡單的中間件函數')
//注意:在當前中間件中的業務處理完畢之后,必須調用next()函數
//表明把流轉關系轉交給下一個中間件或者路由
next()
}

全局生效的中間件

客戶端發起的任何請求,到達服務器之后,都會觸發的中間件,叫做全局生效的中間件。

通過調用 app.use(中間件函數),即可定義一個全局生效的中間件,示例代碼如下:

const mw=function(req,res,next){
console.log('這是要最簡單的中間件函數')
next()
}//全局生效的中間件
app.use(mw)

定義全局中間件的簡化形式

app.use(function(req,res,next){
console.log('這是一個最簡單的中間件函數')
next()
})

中間件的作用

多個中間件之間,共享同一份 req 和 res。基于這樣的特性,我們可以在上游的中間件中,統一為 req 或 res 對象添 加自定義的屬性或方法,供下游的中間件或路由進行使用。

定義多個全局中間件

?可以使用 app.use() 連續定義多個全局中間件。客戶端請求到達服務器之后,會按照中間件定義的先后順序依次進行 調用,示例代碼如下:

app.use(function(req,res,next){
console.log('這是一個第一個中間件函數')
next()
})
app.use(function(req,res,next){
console.log('這是一個第二個中間件函數')
next()
})
app.use(function(req,res,next){
console.log('這是一個第三個中間件函數')
next()
})
局部生效的中間件

不使用 app.use() 定義的中間件,叫做局部生效的中間件,示例代碼如下:

// 定義中間件函數 mw1
const mw1 = function(req, res, next) {console.log('這是中間件函數')next()
}// mw1 這個中間件只在"當前路由中生效",這種用法屬于"局部生效的中間件"
app.get('/', mw1, function(req, res) {res.send('Home page.')
})// mw1 這個中間件不會影響下面這個路由↓↓↓
app.get('/user', function(req, res) { res.send('User page.') })

定義多個局部中間件

?可以在路由中,通過如下兩種等價的方式,使用多個局部中間件:

// 以下兩種寫法是“完全等價”的,可根據自己的喜好,選擇任意一種方式進行使用
app.get('/', mw1, mw2, (req, res) => { res.send('Home page.') })
app.get('/', [mw1, mw2], (req, res) => { res.send('Home page.') })

了解中間件的5個使用注意事項

  • ?① 一定要在路由之前注冊中間件
  • ② 客戶端發送過來的請求,可以連續調用多個中間件進行處理
  • ③ 執行完中間件的業務代碼之后,不要忘記調用 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('Home page .')
})

路由級別的中間件

綁定到 express.Router() 實例上的中間件,叫做路由級別的中間件。它的用法和應用級別中間件沒有任何區別。只不 過,應用級別中間件是綁定到 app 實例上,路由級別中間件綁定到 router 實例上,代碼示例如下:

var app = express()
var router = express.Router()// 路由級別的中間件
router.use(function (req, res, next) {console.log('Time:', Date.now())next()
})app.use('/', router)

錯誤級別的中間件

錯誤級別中間件的作用:專門用來捕獲整個項目中發生的異常錯誤,從而防止項目異常崩潰的問題。 格式:錯誤級別中間件的 function 處理函數中,必須有 4 個形參,形參順序從前到后,分別是 (err, req, res, next)。

app.get('/', function(req, res) {    // 1. 路由throw new Error('服務器內部發生了錯誤!')    // 1.1 拋出一個自定義的錯誤res.send('Home Page.')
})app.use(function (err, req, res, next) {    // 2. 錯誤級別的中間件console.log('發生了錯誤:' + err.message)    // 2.1 在服務器打印錯誤消息res.send('Error!' + err.message)        // 2.2 向客戶端響應錯誤相關的內容
})

Express內置的中間件

自 Express 4.16.0 版本開始,Express 內置了 3 個常用的中間件,極大的提高了 Express 項目的開發效率和體驗:

① express.static 快速托管靜態資源的內置中間件,例如: HTML 文件、圖片、CSS 樣式等(無兼容性)

② express.json 解析 JSON 格式的請求體數據(有兼容性,僅在 4.16.0+ 版本中可用)

③ express.urlencoded 解析 URL-encoded 格式的請求體數據(有兼容性,僅在 4.16.0+ 版本中可用)

// 配置解析 application/json 格式數據的內置中間件
app.use(express.json())// 配置解析 application/x-www-form-urlencoded 格式數據的內置中間件
app.use(express.urlencoded({ extended: false }))

第三方的中間件

非 Express 官方內置的,而是由第三方開發出來的中間件,叫做第三方中間件。在項目中,大家可以按需下載并配置 第三方中間件,從而提高項目的開發效率。

例如:在 express@4.16.0 之前的版本中,經常使用 body-parser 這個第三方中間件,來解析請求體數據。使用步驟如下:

① 運行 npm install body-parser 安裝中間件

② 使用 require 導入中間件

③ 調用 app.use() 注冊并使用中間件

使用Express寫接口

創建基本的服務器

// 導入 express 模塊
const express = require('express')
// 創建 express 的服務器實例
const app = express()// write your code here...// 調用 app.listen 方法,指定端口號并啟動web服務器
app.listen(80, function () {console.log('Express server running at http://127.0.0.1')
})

創建 API 路由模塊?

// apiRouter.js 【路由模塊】
const express = require('express')
const apiRouter = express.Router()// bind your router here...module.exports = apiRouter// app.js 【導入并注冊路由模塊】
const apiRouter = require('./apiRouter.js')
app.use('/api', apiRouter)

編寫 GET 接口

?

apiRouter.get('/get', (req, res) => {// 1. 獲取到客戶端通過查詢字符串,發送到服務器的數據const query = req.query// 2. 調用 res.send() 方法,把數據響應給客戶端res.send({res.send({status: 0,       // 狀態,0 表示成功,1 表示失敗msg: 'GET請求成功!',  // 狀態描述data: query       // 需要響應給客戶端的具體數據})})

編寫 POST 接口

?

apiRouter.post('/post', (req, res) => {// 1. 獲取客戶端通過請求體,發送到服務器的 URL-encoded 數據const body = req.body// 2. 調用 res.send() 方法,把數據響應給客戶端res.send({res.send({status: 0,       // 狀態,0 表示成功,1 表示失敗msg: 'POST請求成功!',  // 狀態描述消息data: body       // 需要響應給客戶端的具體數據})})


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/899528.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/899528.shtml
英文地址,請注明出處:http://en.pswp.cn/news/899528.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue遺漏的知識點(動態組件.組件庫的操作使用)

----動態組件&#xff08;vue2vue3通用&#xff09; <component :is"..."> 的作用 <component> 是 Vue 的內置組件&#xff0c;用于動態渲染其他組件。:is 屬性 用于指定要渲染的組件。它的值可以是&#xff1a; 組件的名稱&#xff08;字符串&#xf…

vue 項目啟動報錯可以讓 cursor啟動

vue 項目啟動報錯可以讓 cursor啟動

SQL EXISTS 與 NOT EXISTS 運算符

EXISTS 和 NOT EXISTS 是 SQL 中的邏輯運算符&#xff0c;用于檢查子查詢是否返回任何行。它們通常用在 WHERE 子句中&#xff0c;與子查詢一起使用。 EXISTS 運算符 EXISTS 運算符用于檢查子查詢是否返回至少一行數據。如果子查詢返回任何行&#xff0c;EXISTS 返回 TRUE&…

Android設計模式之模板方法模式

一、定義&#xff1a; 定義一個操作中的算法的框架&#xff0c;而將一些步驟延遲到子類中&#xff0c;使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。 二、結構&#xff1a; AbstractClass抽象類&#xff1a;定義算法的骨架&#xff0c;包含模板方法和若干…

Vue3當中el-tree樹形控件使用

tree懸停tooltip效果 文本過長超出展示省略號 如果文本超出懸停顯示tooltip效果 反之不顯示 這里直接控制固定寬度限制 試了監聽寬度沒效果<template><el-treeshow-checkbox:check-strictly"true":data"data"node-key"id":props"…

QScreen 捕獲屏幕(截圖)

一、QScreen核心能力解析 硬件信息獲取 // 獲取主屏幕對象 QScreen* primaryScreen QGuiApplication::primaryScreen();// 輸出屏幕參數 qDebug() << "分辨率:" << primaryScreen->size(); qDebug() << "物理尺寸:" << primar…

PDF處理控件Aspose.PDF教程:通過C#、Java 和 Python刪除 PDF中的水印

Aspose.PDF 是一個功能強大的庫&#xff0c;旨在以編程方式處理 PDF 文檔&#xff0c;提供創建、編輯、轉換和操作的廣泛功能。它支持 C#、Java 和 Python 等多種編程語言&#xff0c;使開發人員能夠精確高效地自動處理 PDF。 對于開發人員來說&#xff0c;由于自動化和定制化…

基于STC89C51的太陽自動跟蹤系統的設計與實現—單片機控制步進電機實現太陽跟蹤控制(仿真+程序+原理圖+PCB+文檔)

摘 要 隨著我國經濟的飛速發展&#xff0c;促使各種能源使用入不敷出&#xff0c;尤其是最主要的能源&#xff0c;煤炭石油資源不斷消耗與短缺&#xff0c;因此人類尋找其他替代能源的腳步正在加快。而太陽能則具有無污染﹑可再生﹑儲量大等優點&#xff0c;且分布范圍廣&…

【硬件測試】基于FPGA的16QAM+幀同步系統開發與硬件片內測試,包含高斯信道,誤碼統計,可設置SNR

目錄 1.算法硬件測試效果 2.算法涉及理論知識概要 2.1 16QAM調制解調原理 2.2 幀同步 3.Verilog核心程序 4.開發板使用說明和如何移植不同的開發板 5.完整算法代碼文件獲得 1.算法硬件測試效果 本文是之前寫的文章: 《基于FPGA的16QAM幀同步系統verilog開發,包含testb…

多路徑 TCP 調度的另一面

參考前面的文章 一個原教旨的多路徑 TCP 和 MP-BBR 公平性推演&#xff0c;一直都破而不立&#xff0c;不能光說怎樣不好&#xff0c;還得說說現狀情況下&#xff0c;該如何是好。 如果 receiver 亂序重排的能力有限(拜 TCP 所賜)&#xff0c;如果非要在多路徑上傳輸 TCP&…

大數據學習(92)-spark詳解

&#x1f34b;&#x1f34b;大數據學習&#x1f34b;&#x1f34b; &#x1f525;系列專欄&#xff1a; &#x1f451;哲學語錄: 用力所能及&#xff0c;改變世界。 &#x1f496;如果覺得博主的文章還不錯的話&#xff0c;請點贊&#x1f44d;收藏??留言&#x1f4dd;支持一…

RAG - 五大文檔切分策略深度解析

文章目錄 切分策略1. 固定大小分割&#xff08;Fixed-Size Chunking&#xff09;2. 滑動窗口分割&#xff08;Sliding Window Chunking&#xff09;3. 自然語言單元分割&#xff08;Sentence/Paragraph Segmentation&#xff09;4. 語義感知分割&#xff08;Semantic-Aware Seg…

微信小程序引入TDesign組件后報錯一直提示路徑不對(Component is not found in path)的解決方法

最近在做微信小程序的項目&#xff0c;創建好項目后&#xff0c;按官方方式引入TDesign組件&#xff0c;但還是一直提示報錯&#xff08;Component is not found in path "miniprogram_npm/tdesign-miniprogram/button/button" (using by "pages/login/login&qu…

攔截器和過濾器詳解

在 Java Web 開發中&#xff0c;攔截器&#xff08;Interceptor&#xff09;和過濾器&#xff08;Filter&#xff09;是兩種常見的請求處理機制&#xff0c;它們用于對請求和響應進行預處理和后處理 1. 過濾器&#xff08;Filter&#xff09; 1.1 作用 Filter 主要用于對 請求…

【機械視覺】C#+VisionPro聯合編程———【六、visionPro連接工業相機設備】

【機械視覺】C#VisionPro聯合編程———【六、visionPro連接工業相機設備】 目錄 【機械視覺】C#VisionPro聯合編程———【六、visionPro連接工業相機設備】 前言&#xff1a; 連接步驟說明 一. 硬件連接 支持的相機接口類型&#xff1a; 連接步驟 2. 軟件配置 Visio…

筆記:基于環境語義的通感融合技術,將傳統通信由“被動接收”轉為“主動感知”

《基于計算機視覺的感知通信融合理論與關鍵技術研發進展》 介紹了聯合研發的基于環境語義的通感融合技術研發進展。 觀點&#xff1a;利用環境感知信息或環境語義輔助通信的通感融合技術成為6G重要方向之一 產出&#xff1a;基于環境感知的毫米波波束管理方案&#xff0c;并…

Kafka 多線程開發消費者實例

目前&#xff0c;計算機的硬件條件已經大大改善&#xff0c;即使是在普通的筆記本電腦上&#xff0c;多核都已經是標配了&#xff0c;更不用說專業的服務器了。如果跑在強勁服務器機器上的應用程序依然是單線程架構&#xff0c;那實在是有點暴殄天物了。不過&#xff0c;Kafka …

zynq7000 + ucos3 + lwip202_v1_2調試過程

1 現在裸機應用上驗證lwip 跑起來可能會報錯&#xff0c;看下面的鏈接解決 zynq 網卡Phy setup error問題 zynq 網卡Phy setup error問題-CSDN博客 2 ping同以后&#xff0c;在zynq上添加ucos系統 鏈接如下&#xff1a; ZYNQ移植uCOSIII_zynq ucos-CSDN博客 3 移植lwip協議…

Android7 Input(二)Linux 驅動層輸入事件管理

概述 在Linux系統中&#xff0c;將鍵盤&#xff0c;鼠標&#xff0c;觸摸屏等這類交互設備交由Linux Input子系統進行管理&#xff0c;Linux Input驅動子系統由于具有良好的和用戶空間交互的接口。因此Linux Input驅動子系統&#xff0c;不止于只管理輸入類型的設備。也可以將其…

Java內存中的Heap(堆)的作用

Java內存中的Heap&#xff08;堆&#xff09;的作用 在 Java 的內存模型中&#xff0c;Heap&#xff08;堆&#xff09; 是 JVM&#xff08;Java Virtual Machine&#xff09;管理的運行時數據區域之一&#xff0c;主要用于存儲程序運行過程中動態分配的對象和數據。它是 Java…