前置 Express安裝
- 方式一 : express提供的腳手架,直接創(chuàng)建一個(gè)應(yīng)用的骨架
- 安裝腳手架npm install -g express-generator
- 創(chuàng)建項(xiàng)目 express express-demo
- 安裝依賴npm install
- 啟動(dòng)項(xiàng)目 node bin/www
- 方式二 : 從零搭建自己的express應(yīng)用結(jié)構(gòu);
- 初始化項(xiàng)目 npm init
- 安裝express npm i express
1. 基本使用
- 導(dǎo)入–>創(chuàng)建–>監(jiān)聽
- 使用參考文檔
const express = require('express');
// * 創(chuàng)建express服務(wù)器
const app=express()
// * 啟動(dòng)服務(wù)器 ,監(jiān)聽端口
app.listen(8000,()=>{
console.log('啟動(dòng)express 服務(wù)器')
})
// 請(qǐng)求
app.post('/login',(req,res)=>{
res.end('登錄成功')
})
app.get('/home',(req,res)=>{
res.end('home 列表模塊')
})
2. 中間件
- 中間件的本質(zhì)是傳遞給express的一個(gè)回調(diào)函數(shù);
- 這個(gè)回調(diào)函數(shù)接受三個(gè)參數(shù):
- 請(qǐng)求對(duì)象(request對(duì)象);
- 響應(yīng)對(duì)象(response對(duì)象);
- next函數(shù)(在express中定義的用于執(zhí)行下一個(gè)中間件的函數(shù));
重要
:中間件的執(zhí)行過程,只會(huì)執(zhí)行第一次匹配的中間件,關(guān)于后面是否執(zhí)行看next
app.post('/login', (req, res, next) => {
// 中間件中的req與res可以進(jìn)行修改
res.aaa = '添加aaa并修改res'
// 2. JSON結(jié)束
// res.json({message:'登錄成功',code:200})
// res.end('登錄成功')
// 3. next 匹配執(zhí)行下一個(gè)中間件
next()
})
-
注意點(diǎn)
: 如果當(dāng)前中間件功能沒有結(jié)束請(qǐng)求-響應(yīng)周期,則必須調(diào)用next()這將控制權(quán)傳遞給下一個(gè)中間件功能,否則,請(qǐng)求將被掛起
const express = require('express');
// * 創(chuàng)建express服務(wù)器
const app = express()
// * 啟動(dòng)服務(wù)器 ,監(jiān)聽端口
app.listen(8000, () => {
console.log('啟動(dòng)express 服務(wù)器')
})
// 請(qǐng)求
app.post('/login', (req, res, next) => {
// 中間件中的req與res可以進(jìn)行修改
res.aaa = '添加aaa并修改res'
// 2. JSON結(jié)束
// res.json({message:'登錄成功',code:200})
// res.end('登錄成功')
// 3. next 匹配執(zhí)行下一個(gè)中間件
next()
})
app.use((req,res,next)=>{
console.log('執(zhí)行下一個(gè)中間件next');
})
app.get('/home', (req, res) => {
res.end('home 列表模塊')
})
2.1 中間件應(yīng)用
- express主要提供了兩種方式:
- app/router.use;
- app/router.methods;
app.use
app.use((req,res,next)=>{
console.log('執(zhí)行下一個(gè)中間件next');
})
app.methods
app.get('/home', (req, res) => {
res.end('home 列表模塊')
})
3. 中間件的注冊(cè)方式
3.1 普通中間件的注冊(cè)
-
use注冊(cè)
的中間件不管什么路徑或者請(qǐng)求都可以匹配的上 - 同時(shí)在匹配的過程中如何不
next()
, 只會(huì)執(zhí)行第一個(gè)中間件
// 1. use注冊(cè)的中間件不管什么路徑或者請(qǐng)求都可以匹配的上
// 2. 同時(shí)在匹配的過程中如何不 next(), 只會(huì)執(zhí)行第一個(gè)中間件
app.use((req,res,next)=>{
console.log('執(zhí)行下一個(gè)中間件next');
next()
})
app.use(()=>{
console.log('執(zhí)行第二個(gè)中間件')
})
3.2 path匹配中間件
-路徑匹配中間件只是對(duì)路徑做限制并沒有對(duì)請(qǐng)求方式做顯示
// 這里的路徑匹配中間件只是對(duì)路徑做限制并沒有請(qǐng)求方式做顯示
// 不管method如何都可以匹配
app.use('/home',(req,res,next)=>{
console.log('路徑匹配中間件')
})
3.3 method與路徑匹配
- 語法:
app.method(path,middleware)
- 匹配中間件只會(huì)匹配第一個(gè)符合要求的中間件 , 關(guān)于下一個(gè)中間件是否執(zhí)行看有沒有調(diào)用next
// app.method(path,middleware)
app.get('/home',(req,res,next)=>{
console.log('路徑以及方法匹配');
res.end('匹配成功')
})
// 注冊(cè)多個(gè)中間件
app.get('/home', (req, res, next) => {
console.log('路徑以及方法匹配');
res.end('匹配成功')
// 中間的匹配只會(huì)匹配第一個(gè)符合要求的中間件 , 關(guān)于下一個(gè)中間件是否執(zhí)行看有沒有調(diào)用next
}, (req, res, next)=>{
console.log('關(guān)于這個(gè)中間件的執(zhí)行需要看上一個(gè)中間件是否有next');
})
3.4 案列中間件匹配與執(zhí)行方法
- 普通直接寫法
app.post('/login', (req, res, next) => {
req.on('data', data => {
let userInfo = data.toString()
const user = JSON.parse(userInfo)
if (user.username === 'admin' && user.password===123456) {
res.end('登錄成功')
}else{
res.end('賬號(hào)或者密碼錯(cuò)誤')
}
})
})
// 注冊(cè)信息
app.post('/register', (req, res, next) => {
// res.end('注冊(cè)成功')
// 注冊(cè)要查詢數(shù)據(jù)庫,看是否存在用戶名
if (true) {
req.on('data', data => {
let userInfo = data.toString()
const user = JSON.parse(userInfo)
if (user.username === 'admin' && user.password === 123456) {
res.end('注冊(cè)成功')
} else {
res.end('賬號(hào)或者密碼錯(cuò)誤')
}
})
}
})
- ** 優(yōu)化
JSON解析,放到body后next()
**
// 1. JSON解析,放到body
app.use((req, res, next) => {
if (req.headers['content-type'] === 'application/json') {
req.on('data', data => {
const jsonInfo = JSON.parse(data.toString())
req.body = jsonInfo
})
req.on('end', () => {
next()
})
}
})
// 賬號(hào)密碼
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end('登錄成功')
})
// 注冊(cè)信息
app.post('/register', (req, res, next) => {
console.log(req.body);
})
4. 中間件request數(shù)據(jù)解析
-
express
有內(nèi)置一些幫助我們完成對(duì)request解析的中間件;
4.1 解析request body中間件
app.use((req, res, next) => {
if (req.headers['content-type'] === 'application/json') {
req.on('data', data => {
const jsonInfo = JSON.parse(data.toString())
req.body = jsonInfo
})
req.on('end', () => {
next()
})
}
next()
})
// 賬號(hào)密碼
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end('登錄成功')
})
- 上面代碼中利用
JSON.parse對(duì)data數(shù)據(jù)進(jìn)行解析
,但是express中提供了 json可以直接進(jìn)行解析
app.use(express.json())
// 賬號(hào)密碼
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end('登錄成功')
})
4.2 urlencoded解析
- 解析客戶端利用
urlencoded
傳參 , 這時(shí)就需要用express.urlencoded()
app.use(express.urlencoded()) // 解析客戶端利用urlencoded傳參
// 解決 body - parser deprecated undefined extended: provide extended option 05urlencoded警告
app.use(express.urlencoded({ extended: true }))
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end('登錄成功')
})
5. 第三方中間件
5.1 morgan 日志記錄
const express = require('express');
const morgan = require('morgan');
const fs = require('fs');
const app = express()
// cnpm i morgan 安裝
// 第三方中間件 合并日志
const writerLog=fs.createWriteStream('./log.txt')
// 日志寫入
app.use(morgan('combined', { stream: writerLog }))
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end('登錄成功')
})
5.2 multer 文件上傳
- 安裝
npm i multer --save
-
Multer
只處理任何multipart/form-data
類型的表單數(shù)據(jù)。 -
Multer
會(huì)在express 的 request 對(duì)象里添加一個(gè) body 對(duì)象
(包含表單的文本域信息)以及file
或files
對(duì)象 (單文件通過req.file
獲取,多文件通過req.files
獲取,file 或 files 對(duì)象包含對(duì)象表單上傳的文件信息)。 -
注意點(diǎn)
upload.single的值,對(duì)應(yīng)前端name中的值,同時(shí)也要保住form-data
中key的值相同。
const multer = require('multer');
// 對(duì)上傳的文件名字重起
const upload = multer({
storage: multer.diskStorage({
// 文件名稱,
// destination 是用來確定上傳的文件應(yīng)該存儲(chǔ)在哪個(gè)文件夾中
// destination 是一個(gè)函數(shù),必須創(chuàng)建這個(gè)文件夾
destination(require, file, callback) {
callback(null, 'uploads/')
},
filename(require, file, callback) {
// originalname是文件上傳時(shí)的名字,可以根據(jù)它獲取后綴
callback(null, Date.now() + '_' + file.originalname)
}
})
})
app.post('/upload', upload.single("file"), (req, res, next) => {
console.log(req.file); // 文件信息
res.end('文件上傳成功')
})
- 多文件上傳 ,接受的是一個(gè)數(shù)組
- 同時(shí)在
multer實(shí)例.array(fielname[,maxCount])
——接收一個(gè)以fielname命名的文件數(shù)組
;maxCount——限制上傳的最大數(shù)量,這些文件的信息保存在req.files里面
app.post('/upload', upload.array("file"), (req, res, next) => {
console.log(req.files); // 文件信息
res.end('文件上傳成功')
})
參考解析
- storage存儲(chǔ)引擎以及錯(cuò)誤處理
- 前后端上傳案例
解析form-data中的普通數(shù)據(jù)
const formData= multer()
app.post('/login',formData.any(), (req, res, next) => {
console.log(req.body);
res.end('登錄成功')
})
6. 參數(shù)解析 params和query
- query 主要用于分頁
app.post('/list', (req, res, next) => {
// http://localhost:8000/list?offset=10&page=20解析
console.log(req.query); // { offset: '10', page: '20' }
res.end('登錄成功')
})
- params 主要用于id的傳遞
app.post('/user/:id', (req, res, next) => {
// http://localhost:8000/user/1100
const id = req.params.id
res.end(`獲取用戶${id}`)
})
7. 響應(yīng)數(shù)據(jù)
-
end方式
: 類似于http中的response.end方法,用法是一致的 -
json方法
: json方法中可以傳入很多的類型:object、array、string、boolean、number、null等,它們會(huì)被轉(zhuǎn)換成json格式返回 -
status方法
: 用于設(shè)置狀態(tài)碼;注意
是函數(shù) - 其他響應(yīng)內(nèi)容參考
app.get('/login', (req, res, next) => {
// 1. 方法一 end
// res.end(`響應(yīng)數(shù)據(jù)---登錄成功`)
// 2. JSON數(shù)據(jù)響應(yīng)
// res.json({
// code: 0, message: '歡迎回來', data: [{
// name: "admin",
// avator:'www.http.ccc.jpg'
// }]
// })
// 3. status 方法,設(shè)置http狀態(tài)碼
res.status(201)
res.json(
{
code: 0, message: '歡迎回來', data: [{
name: "admin",
avator: 'www.http.ccc.jpg'
}]
}
)
})
8. 路由
-
express.Router
來創(chuàng)建一個(gè)路由處理程序
useRouter.js
const express = require('express');
const userRouter = express.Router()
userRouter.get('/', (req, res, next) => {
res.json(
{
code: 0, message: 'success', data: [{
name: "admin",
password:'123456'
}, {
name: "admin",
password: '123456'
}]
}
)
})
userRouter.get('/:id',(req, res, next) => {
const id=req.params.id
res.end(id)
})
userRouter.post('/', (req, res, next) => {
})
userRouter.delete('/:id', (req, res, next) => {
})
userRouter.patch('/:id', (req, res, next) => {
})
module.exports=userRouter
index.js文章來源:http://www.zghlxwxcb.cn/news/detail-603502.html
const userRouter = require('./router/userRouters.js');
app.use('/users', userRouter)
參考文章 :路由在項(xiàng)目中的具體使用文章來源地址http://www.zghlxwxcb.cn/news/detail-603502.html
9. 靜態(tài)資源
-
express 內(nèi)置static() 靜態(tài)資源
,直接將文件夾做一個(gè)靜態(tài)資源
app.use(express.static('./uploads'))
10 錯(cuò)誤處理
- 普通的錯(cuò)誤處理,需要利用前端的數(shù)據(jù)進(jìn)行if判斷處理
- 但是每一個(gè)接口寫一個(gè)判斷或者返回的錯(cuò)誤信息以及狀態(tài)碼相同,這就會(huì)造成代碼的甬余
app.post('/login', (req, res, next) => {
const { username, password } = req.body
if (username !== 'admin' || password !== 123456) {
res.json({
code: 1002,
message: '賬號(hào)密碼錯(cuò)誤'
})
} else {
console.log('xx')
res.json({
code: 200,
message: '登錄成功'
})
}
})
- 簡單封裝統(tǒng)一處理
// 中間件處理錯(cuò)誤信息
app.post('/login', (req, res, next) => {
if (username !== 'admin' || password !== 123456) {
next(1002)
}
else {
next()
}
})
app.use((errCode, req, res, next) => {
const code = errCode
let message = ''
switch (code) {
case 1001:
message = '未知的錯(cuò)誤'
break
case 1002:
message = '賬號(hào)或密碼錯(cuò)誤'
default:
message = '登錄成功'
}
res.json({
code: errCode,
message,
})
})
到了這里,關(guān)于node中間件-express框架的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!