原生http在進行很多處理時,會較為復(fù)雜;有URL判斷、Method判斷、參數(shù)處理、" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁 > 營銷資訊 > 網(wǎng)站運營 > Node.js——express開發(fā)web服務(wù)器

Node.js——express開發(fā)web服務(wù)器

時間:2023-05-25 04:09:02 | 來源:網(wǎng)站運營

時間:2023-05-25 04:09:02 來源:網(wǎng)站運營

Node.js——express開發(fā)web服務(wù)器:

一. Express初體驗

1.1. 認識Web框架

前面我們已經(jīng)學(xué)習(xí)了使用http內(nèi)置模塊來搭建Web服務(wù)器,為什么還要使用框架?

目前在Node中比較流行的Web服務(wù)器框架是express、koa;

express早于koa出現(xiàn),并且在Node社區(qū)中迅速流行起來:

1.2. express的安裝

express的使用過程有兩種方式:

方式一:安裝express-generator

npm install -g express-generator創(chuàng)建項目:

express express-demo項目目錄如下:

├── app.js├── bin│ └── www├── package-lock.json├── package.json├── public│ ├── images│ ├── javascripts│ └── stylesheets│ └── style.css├── routes│ ├── index.js│ └── users.js└── views ├── error.jade ├── index.jade └── layout.jade我們可以安裝依賴,將程序跑起來:

npm installnode bin/www方式二:從零學(xué)習(xí)搭建

剛才創(chuàng)建的項目express項目,很多內(nèi)容可能我們并不認識,所以剛開始我們最好從零來學(xué)習(xí)。

初始化一個新的項目

npm init -yexpress的安裝:

npm install express

1.3. express初體驗

我們來創(chuàng)建自己的第一個express程序:

const express = require('express');// 創(chuàng)建服務(wù)器const app = express();// /home的get請求處理app.get("/home", (req, res) => { res.end("Hello Home");});// /login的post請求處理app.post("/login", (req, res) => { res.end("Hello Login");});// 開啟監(jiān)聽app.listen(8000, () => { console.log("服務(wù)器啟動成功~");})我們會發(fā)現(xiàn),之后的開發(fā)過程中,可以方便的將請求進行分離:

當(dāng)然,這只是初體驗,接下來我們來探索更多的用法;

1.4. 請求和響應(yīng)

請求的路徑中如果有一些參數(shù),可以這樣表達:

返回數(shù)據(jù),我們可以方便的使用json:

const express = require('express');const app = express();app.get('/users/:userId', (req, res, next) => { console.log(req.params.userId); res.json({username: "coderwhy", level: 99});});app.listen(8000, () => { console.log("靜態(tài)服務(wù)器啟動成功~");})

二. Express中間件

2.1. 認識中間件

Express是一個路由和中間件的Web框架,它本身的功能非常少:

中間件是什么呢?




中間件中可以執(zhí)行哪些任務(wù)呢?

如果當(dāng)前中間件功能沒有結(jié)束請求-響應(yīng)周期,則必須調(diào)用next()將控制權(quán)傳遞給下一個中間件功能,否則,請求將被掛起。

中間件函數(shù)調(diào)用的元素:







image-20201101205333843

2.2. 應(yīng)用中間件

那么,如何將一個中間件應(yīng)用到我們的應(yīng)用程序中呢?

我們先來學(xué)習(xí)use的用法,因為methods的方式本質(zhì)是use的特殊情況;

案例一:最普通的中間件

之所以稱之為最普通的中間件,是因為無論是什么path、methods都會應(yīng)用該中間件;

const express = require('express');const app = express();app.use((req, res, next) => { console.log("common middleware 01"); next();})app.use((req, res, next) => { console.log("common middleware 02"); res.end("Hello Common Middleware~");})app.listen(8000, () => { console.log("中間件服務(wù)器啟動成功~");})中間件的執(zhí)行順序:

案例二:path匹配中間件

如果我們希望匹配一個明確的路徑,也可以使用use方法:

// 案例二: 路徑匹配中間件app.use('/home', (req, res, next) => { console.log("home middleware 01"); next();});app.use('/home', (req, res, next) => { console.log("home middleware 02"); next(); res.end("Hello Home middleware");});app.use((req, res, next) => { console.log("common middleware");});案例三:path和method匹配中間件

// 案例三: method匹配中間件app.get('/home', (req, res, next) => { console.log("home get middleware"); next();})app.post('/login', (req, res, next) => { console.log("login post middleware"); next();});app.use((req, res, next) => { console.log("common middleware");});案例四:注冊多個中間件

// 案例四: 注冊多個中間件const homeMiddleware1 = (req, res, next) => { console.log('home middleware 01'); next();}const homeMiddleware2 = (req, res, next) => { console.log('home middleware 02'); next();}const homeHandle = (req, res, next) => { res.end("Hello Home~");}app.get('/home', homeMiddleware1, homeMiddleware2, homeHandle);

2.3. 應(yīng)用其他中間件

并非所有的中間件都需要我們從零去編寫:

2.3.1. request解析中間件

在客戶端發(fā)送post請求時,會將數(shù)據(jù)放到body中:

我們這里先使用json傳遞給服務(wù)器body:







json傳遞body

不進行解析時的操作:

app.post('/login', (req, res, next) => { req.on('data', (data) => { console.log(data.toString()); }) req.on('end', () => { res.end("登錄成功~"); });});我們也可以自己編寫中間件來解析JSON:

app.use((req, res, next) => { if (req.headers['content-type'] === 'application/json') { req.on('data', (data) => { const userInfo = JSON.parse(data.toString()); req.body = userInfo; }) req.on('end', () => { next(); }) } else { next(); }})app.post('/login', (req, res, next) => { console.log(req.body); res.end("登錄成功~");});但是,事實上我們可以使用expres內(nèi)置的中間件或者使用body-parser來完成:

app.use(express.json());app.post('/login', (req, res, next) => { console.log(req.body); res.end("登錄成功~");});如果我們解析的是 application/x-www-form-urlencoded







form傳遞body

我們可以使用express自帶的 urlencoded函數(shù)來作為中間件:




app.use(express.json());app.use(express.urlencoded({extended: true}));app.post('/login', (req, res, next) => { console.log(req.body); res.end("登錄成功~");});

2.3.2. 日志記錄中間件

如果我們希望將請求日志記錄下來,那么可以使用express官網(wǎng)開發(fā)的第三方庫:morgan

安裝morgan:

npm install morgan直接作為中間件使用即可:

const loggerWriter = fs.createWriteStream('./log/access.log', { flags: 'a+'})app.use(morgan('combined', {stream: loggerWriter}));

2.3.3. 上傳文件中間件

圖片上傳我們可以使用express官方開發(fā)的第三方庫:multer

npm install multer上傳文件,并且默認文件名:

const upload = multer({ dest: "uploads/"})app.post('/upload', upload.single('file'), (req, res, next) => { console.log(req.file.buffer); res.end("文件上傳成功~");})添加文件名后綴:

const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, "uploads/") }, filename: (req, file, cb) => { cb(null, Date.now() + path.extname(file.originalname)); }})const upload = multer({ storage})app.post('/upload', upload.single('file'), (req, res, next) => { console.log(req.file.buffer); res.end("文件上傳成功~");})我們也可以上傳多張圖片:

app.use('/upload', upload.array('files'), (req, res, next) => { console.log(req.files);});如果我們希望借助于multer幫助我們解析一些form-data中的普通數(shù)據(jù),那么我們可以使用any:







image-20201104165039444

app.use(upload.any());app.use('/login', (req, res, next) => { console.log(req.body);});

2.4. 請求和響應(yīng)

客戶端傳遞到服務(wù)器參數(shù)的方法常見的是5種:

2.4.1. 請求解析

方式一:params

請求地址:http://localhost:8000/login/abc/why

獲取參數(shù):

app.use('/login/:id/:name', (req, res, next) => { console.log(req.params); res.json("請求成功~");})方式二:query

請求地址:http://localhost:8000/login?username=why&password=123

獲取參數(shù):

app.use('/login', (req, res, next) => { console.log(req.query); res.json("請求成功~");})

2.4.2. 響應(yīng)方式

end方法

類似于http中的response.end方法,用法是一致的

res.end("Hello World");json方法

json方法中可以傳入很多的類型:object、array、string、boolean、number、null等,它們會被轉(zhuǎn)換成json格式返回;

res.json({name: "why", age: 18});status方法

用于設(shè)置狀態(tài)碼:

res.status(204);

三. 其他支持補充

3.1. 路由的使用

如果我們將所有的代碼邏輯都寫在app中,那么app會變得越來越復(fù)雜:




我們可以使用 express.Router來創(chuàng)建一個路由處理程序:

// 用戶相關(guān)的處理const userRouter = express.Router();userRouter.get('/', (req, res, next) => { res.end("用戶列表");});userRouter.post('/', (req, res, next) => { res.end("創(chuàng)建用戶");});userRouter.delete('/', (req, res, next) => { res.end("刪除用戶");});app.use('/users', userRouter);當(dāng)然,我們可以配置更多的路由,并且將所有的邏輯放到一個單獨的文件中。

3.2. 靜態(tài)資源服務(wù)器

部署靜態(tài)資源我們可以選擇很多方式:

const express = require('express');const app = express();app.use(express.static('./build'));app.listen(8000, () => { console.log("靜態(tài)服務(wù)器啟動成功~");})

3.3. 錯誤處理方式

app.use((req, res, next) => { next(new Error("USER DOES NOT EXISTS"));});app.use((err, req, res, next) => { const message = err.message; switch (message) { case "USER DOES NOT EXISTS": res.status(400).json({message}) } res.status(500)})

3.4. 源碼分析

3.4.1. 創(chuàng)建app的過程

express函數(shù)的本質(zhì)其實是createApplication







image-20201102161803339

當(dāng)我們調(diào)用app.listen的時候,本質(zhì)上是調(diào)用proto中的listen







image-20201102161939032

3.4.2. 注冊中間件

比如我們通過use來注冊一個中間件,源碼中發(fā)生了什么?







image-20201102162627758

我們來看一下router.use中又做了什么事情?







image-20201102162749391

3.4.3. 請求的處理過程

如果有一個請求過來,那么從哪里開始呢?







image-20201102162943190

app.handle本質(zhì)上會去調(diào)用router.handle:







image-20201102163035566

router.handle中做的什么事情呢?







image-20201102163153121








關(guān)鍵詞:服務(wù)

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點擊下載Chrome瀏覽器
關(guān)閉