基于 Node.js 平台,快速、开放、极简的 Web 开发框架
Express 是用于快速创建服务器的第三方模块。
安装 Express:
npm install express
创建服务器,监听客户端请求,并返回内容:
使用 npx nodemon 运行
const express = require('express')
// 创建 web 服务器
const app = express()
// 监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get('/user', (req, res) => {
res.send({ name: 'zs', age: 20, gender: '男'
})
})
app.post('/user', (req, res) => {
res.send('请求成功')})app.get('/', (req, res) => {
// 通过 req.query 可以获取到客户端发送过来的查询参数
console.log(req.query)
res.send(req.query)
})
// 这里的 :id 是一个动态的参数
app.get('/user/:ids/:username', (req, res) => {
// req.params 是动态匹配到的 URL 参数,默认是一个空对象
console.log(req.params)
res.send(req.params)
})
app.listen(80, () => {
console.log('express server running at <http://127.0.0.1>')
})
res.send()
app.get('/user',(req,res)=>{
res.send({name:'lhd',age:'19'})
})
req.query
app.get('/',(req,res)=>{
console.log(req.query)
})
通过 req.params 对象,可以访问到 URL 中,通过 :
匹配到的动态参数
// 访问 <http://127.0.0.1/user/1874>
app.get('/user/:id',(req,res)=>{
res.send(req.params) // 返回 {id:'1874'}
})
// 访问 <http://127.0.0.1/user/1874/lhd>
app.get('/user/:id/:name',(req,res)=>{
res.send(req.params) // 返回 {id:'1874',name:'lhd'}
})
express.static()
方法可创建静态资源服务器,向外开放访问静态资源。app.use(express.static('public'))
app.use(express.static('files'))
app.use('/bruce', express.static('bruce'))
/*可直接访问 public, files 目录下的静态资源http://localhost:3000/images/bg.jpg
<http://localhost:3000/css/style.css>
<http://localhost:3000/js/login.js>
通过带有 /bruce 前缀的地址访问 bruce 目录下的文件http://localhost:8080/bruce/images/logo.png*/
在 Express 中,路由指的是客户端的请求与服务器处理函数之间的映射关系。
Express 中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数。
// METHOD:请求方式,PATH:请求路径,HANDLER:处理函数
app.METHOD(PATH,HANDLER)
// req:请求对象(包含了与请求相关的属性和方法)
// res:响应对象(包含了与响应相关的属性和方法)
app.get('请求url',function(req,res){
// 处理函数
})
// req:请求对象(包含了与请求相关的属性和方法)
// res:响应对象(包含了与响应相关的属性和方法)
app.post('请求url',function(req,res){
// 处理函数
})
为了方便对路由进行模块化管理,Express 不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。
步骤:
router.js:
const express = require('express')
// router.jsconst express = require('express')
// 创建路由对象
const router = express.Router()
// 挂载具体路由
router.get('/user/list', (req, res) => {
res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
res.send('Add new user.')
})
// 向外导出路由对象
module.exports = router
注册路由模块:
module.js:使用 router.js 中的路由
const express = require('express')
const router = require('./router')
const app = express()
// 注册路由模块,添加访问前缀,前缀可以省略
app.use('/api', router)
app.listen(80, () => {
console.log('<http://127.0.0.1>')
})
请求到达 Express 服务器之后,可连续调用多个中间件,从而对这次请求进行预处理。和vue的路由守卫一样,next()代表放行
中间件是指流程的中间处理环节
服务器收到请求后,可先调用中间件进行预处理
中间件是一个函数,包含 req, res, next
三个参数,next()
参数把流转关系交给下一个中间件或路由
中间件注意事项;
next()
函数next()
函数后别写代码req
、 res
对象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>')
})
next() 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由。
const express = require("express")
const app = express()
// mw 指向的就是一个中间件函数
const mw = function(req.res,next){
console.log('这是个简单的中间件函数')
next()
}
app.listen(80, ()=>{
console.log("DDD")
}
只要有请求到达服务器,必先经过mw中间件函数处理。相对于vue前置守卫,拦截器
// mw 指向的就是一个中间件函数
const mw = function(req.res,next){
console.log('这是个简单的中间件函数')
next()
}
// 全局生效的中间件
app.use(mw)
app.get("/", (req, res) => {
res.send("hhh")
})
简化
app.use(function(req,res,next){
console.log('这是给简单的中间件函数')
next()
})
按注册顺序排,且必须在路由上方。多个中间件共享req和res。
// 完整示例
const express = require('express')
const app = express()
app.use((req, res, next) => {
console.log('第一个中间件')
next()
})
app.use((req, res, next) => {
console.log('第二个中间件')
next()
})
app.get('/', (req, res) => {
res.send({ info: '请求了服务器', method: req.method })
})
app.listen(80, () => {
console.log('<http://127.0.0.1>')
})
const express = require('express')
const app = express()
// 定义中间件函数
const mw1 = (req, res, next) => {
console.log('调用了第一个局部生效的中间件')
next()}
const mw2 = (req, res, next) => {
console.log('调用了第二个局部生效的中间件')
next()
}
// 两种定义局部中间件的方式
app.get('/hello', mw2, mw1, (req, res) => res.send('hello page.'))
app.get('/about', [mw1, mw2], (req, res) => res.send('about page.'))
app.get('/user', (req, res) => res.send('User page.'))
app.listen(80, function () {
console.log('Express server running at <http://127.0.0.1>')
})
不用 app.use() 定义的中间件,叫做局部生效的中间件
const mw = function(req,res,next){
console.log('中间件函数')
next()
}
app.get('/',mw,(req,res)=>{
res.send('Hellow World')
})
app.get('/user',(req,res)=>{
res.send('Hellow World')
})
// mw1与mw2 为中间件函数,两种方式等价
app.get('/',mw1,mw2,(req,res)=>{ xxx })
app.get('/',[mw1,mw2],(req,res)=>{ xxx })
多个中间件之间,共享同一份req和res。基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性或方法,供下游的中间件或路由进行使用。
// 示例:每个请求都需要获取时间
app.use((req, res, next) => {
req.startTime = Date.now()
next()
})
app.get('/user',(req,res)=>{
res.send('time:'+req.startTime)
})
app.use()
或 app.get()
或 app.post()
,绑定到 app
实例上的中间件// 应用级别中间件起(全局中间件)
app.use((req, res, next) => {
next()
})
// 应用级别中间件(局部中间件)
app.get('/user', mw1 ,(req,res)=>{
res.send('time:'+req.startTime)
})
express.Router()
实例上的中间件,叫做路由级别的中间件。用法和应用级别中间件没有区别。应用级别中间件是绑定到 app
实例上,路由级别中间件绑定到 router
实例上。const app = express()
const router = express.Router()
router.use(function (req, res, next) {
console.log(1)
next()
})
app.use('/', router)
(err, req, res, next)
。const express = require('express')
const app = express()
app.get('/', (req, res) => {
throw new Error('服务器内部发生了错误!')
res.send('Home page.')
})
// 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err, req, res, next) => {
console.log('发生了错误!' + err.message)
res.send('Error:' + err.message)
})
app.listen(80, function () {
console.log('Express server running at <http://127.0.0.1>')
})
自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了 Express 项目的开发效率和体验:
express.static
快速托管静态资源的内置中间件,例如: HTML 文件、图片、CSS 样式等(无兼容性)express.json
解析 JSON 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)express.urlencoded
解析 URL-encoded 格式的请求体数据(有兼容性,仅在 4.16.0+ 版本中可用)