上一章我们在使用 http
内置模块来搭建 Web
服务器的过程中,会感到很多问题,那就是原生 http 模块
在进行很多处理时会较为复杂,比如:
URL
判断Method
判断都需要我们自己来处理和封装,当所有的内容都放在一起时,常常会显得非常混乱。
而这些都是框架能帮我们解决的问题
目前在 Node
中比较流行的 Web
服务器框架是 express
和 koa
,express
要早于 koa
出现,并且在 Node
社区中迅速流行起来。
express
快速、方便的开发自己的 Web
服务器Express
整个框架的核心就是中间件,理解了中间件其他一切都非常简单!
express
的使用过程有两种方式:
通过 express
提供的脚手架 express-generator
,直接创建一个应用的骨架
从 0
搭建自己的 express
应用结构
npm install express-generator -g
express express-generator-demo
npm install
npm run start
localhost:3000
,访问成功,表示服务已启动0
搭建express
mkdir express-demo cd express-demo npm init npm i express
01_express的基本使用.js
jsconst express = require("express");
// 创建服务器
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");
});
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
node 01_express的基本使用.js
http://localhost:8000/home
地址Express
是一个路由和中间件的 Web
框架,它本身的功能非常少,它的序本质上是一系列中间件函数的调用
中间件而定本质是传递给 express
的一个回调函数,这个回调函数接受三个参数:
如果当前中间件功能没有 结束请求-相应周期,则必须调用 next()
将控制权传递给下一个中间件功能,否则,请求将被挂起。
express
主要提供两种方式:
app/router.use
;app/router.methods
(methods 指的是常用的请求方式,比如 get
post
)当 express
接收到客户端发送的网络请求时,在所有中间件中开始进行匹配。
当匹配到第一个符合要求的中间件时,那么就会执行这个中间件
后续的中间件是否执行,取决于上一个中间件有没有执行 next
use
方法注册的中间件是最普通/简单的中间件use
注册的中间件,无论是什么请求方式都可以匹配上jsconst 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.listen(8000, () => {
console.log("服务器启动成功~");
});
启动服务,访问 localhost:8000
下面的两个中间件会依次执行
路径匹配的中间件不会对请求方式进行限制
jsconst express = require("express");
// 创建服务器
const app = express();
// 注册路径匹配中间件
app.use('/home',(req,res,next) => {
console.log('我是匹配到 /home 执行的中间件')
})
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
启动服务,访问 http://localhost:8000/home
,只有访问 '/home' 路径才会执行上面的中间件
如果相对路径和请求方式都做限制可以使用 app.method(path, middleware)
的方式
jsconst express = require("express");
// 创建服务器
const app = express();
app.get('/home',(req,res,next) => {
console.log('我是匹配到 /home 的 get 请求时执行的中间件')
})
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
只有当匹配到 /home
的 get
请求时才执行上面的中间件
当我们相对某个复杂的操作进行拆分的时候,就可以使用以下方式注册多个中间件
app.get(路径,中间件1,中间件2,中间件3)
jsconst express = require("express");
// 创建服务器
const app = express();
app.get(
"/home",
(req, res, next) => {
console.log("我是匹配到 /home 的 get 请求时执行的中间件1");
next()
},
(req, res, next) => {
console.log("我是匹配到 /home 的 get 请求时执行的中间件2");
next()
},
(req, res, next) => {
console.log("我是匹配到 /home 的 get 请求时执行的中间件3");
next()
}
);
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
并非所有的中间件都需要我们从零去编写:
express
有内置一些帮助我们完成对 request
解析的中间件;registry
仓库中也有很多可以辅助我们开发的中间件;在客户端发送post请求时,会将数据放到body中:
如果让我么你自己写中间件的话,通常需要做一些额外的逻辑判断
jsconst express = require("express");
// 创建服务器
const app = express();
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 {
}
})
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
但是,事实上我们可以使用 expres
内置的中间件或者使用 body-parser
来完成
jsapp.use(express.json())
就像上面,我们只需要一行代码即可搞定,非常方便
如果解析的是 application/x-www-form-urlencoded
,可以使用
app.use(express.urlencoded({extended: true}))
如果我们希望将请求日志记录下来,那么可以使用 express
官网开发的第三方库:morgan
因为是第三方库,所以需要先单独安装 morgan
npm i morgan
jsconst fs = require("fs");
const express = require("express");
const morgan = require("morgan");
const loggerWriter = fs.createWriteStream("./log/access.log", {
flags: "a+",
});
// 创建服务器
const app = express();
app.use(morgan("combined", { stream: loggerWriter }));
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
启动服务,接着在 ./log
目录下就会保存我们所有的请求日志了
上传文件,我们可以使用 express
提供的 multer
来完成:
同样需要先安装 multer
:
npm i multer
jsconst express = require("express");
const multer = require("multer");
const path = require("path");
// 创建服务器
const app = express();
const upload = multer({
storage: multer.diskStorage({
destination(req, file, cb) {
cb(null, "uploads/");
},
filename: (req, file, cb) => {
cb(null, Date.now() + "_" + path.extname(file.originalname));
},
}),
});
// 单文件上传
app.post("/upload", upload.single("file"), (req, res, next) => {
console.log(req.file);
res.end("文件上传成功");
});
// 多文件上擦混
app.post("/photos", upload.array("photos"), (req, res, next) => {
console.log(req.files);
res.end("文件上传成功");
});
// 开启监听
app.listen(8000, () => {
console.log("服务器启动成功~");
});
接着我们尝试通过 postman
上传一张图片
如果我们希望借助于 multer
帮助我们解析一些 form-data
中的普通数据,那么我们可以使用 any
jsapp.use(upload.any())
app.use('login', (req,res,next) => {
console.log(req.body)
})
客户端传递到服务器参数的方法常见的是 5
种:
get
请求中的 URL
的 params
;get
请求中的 URL
的 query
;post
请求中的 body
的 json
格式(中间件中已经使用过);post
请求中的 body
的 x-www-form-urlencoded
格式(中间件使用过);post
请求中的 form-data
格式(中间件中使用过);关于传递参数 params
和 query
的使用也是非常简单的
请求地址:http://localhost:8000/login/abc/zhangsan
jsapp.use('/login/:id/:name',(req,res,next) => {
console.log(req.params)
res.json('请求成功')
})
请求地址:http://localhost:8000/login?username=zhangsan&password=123456
jsapp.use('/login',(req,res,next) => {
console.log(req.qeury)
res.json('请求成功')
})
jsapp.use((err, req, res, next) => {
const message = err.message;
switch (message) {
case "USER DOES NOT EXISTS":
res.status(400).json({ message });
}
res.status(500);
});
部署静态资源我们可以选择很多方式:
Node
也可以作为静态资源服务器,并且 express
给我们提供了方便部署静态资源的方法;jsconst express = require("express");
const app = express()
app.use(express.static('./build'))
app.listen(8000, ()) => {
console.log('静态服务器启动成功')
})
本文作者:叶继伟
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!