文章目录
express
npm i express
1 创建一个基本的express服务器
// 引入express
const express = require('express')
// 创建express实例
const app = express()
// 在app上挂在路由
app.get('/list',(req, res)=> {})
app.post('/add', (req, res)=> {})
// 启动服务器,监听端口
app.listen(1001, ()=> {
})
2 获取客户端传递的参数
2.1 通过 res.query()
获取 get
请求url中传递的参数
// 请求地址 http://localhost:1001/list?id=1?status=2
app.get('/list', (req, res)=> {
console.log(req.query)
// {id: 1, status: 2}
})
2.2 通过res.params
可以获取到,url中,通过:
匹配到的动态参数
// 请求地址 http://localhost:1001/add/1/张三
app.get('/add/:id/:name', (req, res)=> {
console.log(req.params)
// {id: 1}
})
2.3 获取post请求参数
// 通过 express.json() 这个中间件,解析表单中的 JSON 格式的数据,没有使用这个中间件res.body为undefined
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.post('/add', (req, res)=> {
res.send({
code: 0,
msg: '操作成功',
data: [req.body]
})
})
3 express.static() 静态托管
3.1 托管一个静态资源文件
// 这就就可以访问public文件下的内容了
// 如果服务运行在 http://localhost:1001
// 通过http://localhost:1001/index.html 就可以访问到public文件下index.html文件
app.use(express.static('./public'))
3.2 托管多个静态资源文件
如果托管多个静态资源目录,就多次调用express.staitc()
// node会按照调用的顺序去执行查找静态资源
// 如果两个都有index.js,在第一个中找到直接返回,就不会去第二个找了
// 如果第一个没找到,回去第二个中查找
app.use(express.static('./public'))
app.use(express.static('./file'))
3.3 挂载静态资源的前缀
// 没有添加前缀
// http://localhost:1001/index.html 就能访问
app.use(express.static('./public'))
// 添加前缀
// http://localhost:1001/file/index.html 才能访问
app.use('file',express.static('./file'))
4 nodemon安装使用
全局安装npm install -g nodemon
启动命令nodemon .\index.js
5 路由
客户端的请求 与 服务端的处理函数 的 映射关系
路由包含三部分:请求方式,请求地址,处理函数
app.post(path, (req, res)=> {})
app.get(path, (req, res)=> {})
5.1 路由的基本使用
app.get('/list', ()=> {})
app.post('/add', ()=> {})
5.2 模块化路由
为了方便对路由进行模块化的管理,不建议将路由挂载到app(express实例)上,而是推荐将路由抽离为单独的模块
具体步骤:
- 创建路由模块对应的
.js
文件 - 调用
express.Router()
创建一个路由对象 - 向路由对象上挂在路由
- 通过
module.exports
向外共享路由对象 - 使用app.use注册路由模块
示例代码:
Router
-------路由模块
index.js
------入口文件
index.js
文件
// 引入express模块
const express = require('express')
// 引入user路由模块
const user = require('./Router/user')
// 引入manager路由模块
const manager = require('./Router/manager')
// 创建express实例
const app = express()
// 注册中间件(中间件是按照顺序执行的)
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use('/user', user)
app.use('/manager', manager)
app.listen(1002, ()=> {
console.log('server running at http://127.0.0.1:1002')
})
user.js
模块
// 引入express模块
const express = require('express')
// 创建Router实例
const Router = express.Router()
// 在Router上挂载路由
Router.get('/list',(req, res)=> {
res.send(req.query)
// http://127.0.0.1:1002/user/list?name=lily&age=20
// {"name":"lily","age":"20"}
})
Router.post('/add',(req, res)=> {
res.send(req.body)
// http://127.0.0.1:1002/user/add 入参为{"message":"这是一条测试消息"}
// {"message":"这是一条测试消息"}
})
// 向外暴露Router
module.exports = Router
manager
模块
const express = require('express')
const Router = express.Router()
Router.get('/list', (req, res)=> {
res.send(req.query)
// http://127.0.0.1:1002/manager/list?id=1&name=Tom&age=20
// {"id":"1","name":"Tom","age":"20"}
})
Router.post('/add', ()=> {
res.send(req.body)
// http://127.0.0.1:1002/manager/add 入参是{"message":"这是一条测试消息"}
// {"message":"这是一条测试消息"}
})
module.exports = Router
6 express中间件
中间件是业务处理环境中的中间处理环境,有输入有输出。
客户端请求 ===> 中间件1 ===> 中间件2 ===> 中间3 ===> 最终处理,并详情此次请求 ===> 客户端
-
通过
app.use()
注册全局中间件const express = require('express') const app = express() // 定义中间件函数 const momFun = (req, res, next)=> { console.log('我是全局中间件') next() } // 注册全局中间件 app.use(momFun) // 简化形式 app.use((req, res, next)=>{ next() }) app.get('/', (res, req)=> { ... })
-
局部中间件
回调函数中,有形参next为中间件函数,没有形参next为路由函数const express = require('express') const app = express() // 中间件函数 app.get('/user', (req, res, next)=> { next() }) // 路由函数 app.get('/user', (req, res)=>{})
6.1 中间件的格式
// 在回调函数中,包含形参next
,next()
是多个中间件连续调用的关键,它表示把流转关系转交到下一个中间件或者路由
const express = require('express')
const app = express()
// 定义一个全局中间件
app.use((req, res, next)=>{
next()
})
app.listen(1003, ()=>{})
6.2 定义一个中间件函数
const express = require('express')
const app = express()
// 定义一个全局中间件
app.use((req, res, next)=>{
next()
})
app.get('/list',(req, res)=> {
res.send('哈哈')
})
app.listen(1003, ()=>{})
6.2.1 定义一个全局生效的中间件
上面的例子就是注册全局中间件的例子
6.2.2 定义一个局部中间件
不使用app.use()
注册的中间件,而是放在路由的参数中
const express = require('express')
const app = express()
const fun1 = function(req, res, next) {
// ...
next()
}
app.get('/list', fun1, (req, res)=> {
// ....
})
代码示例:
const express = require('express')
const app = express()
app.use((req, res, next)=> {
req.number = 10
next()
})
fun1 = (req, res, next)=> {
req.myParams = {
value: '哈哈哈',
id: 1
}
req.str = '11111'
next()
}
app.get('/list1', (req, res)=> {
console.log(req.number) // 10
req.number = 20
console.log(req.myParams) // undefined
console.log(req.str) // undefined
res.send('操作成功')
})
app.get('/list2', fun1, (req, res)=> {
console.log(req.number) // 10
console.log(req.myParams) // { value: '哈哈哈', id: 1 }
console.log(req.str) // 11111
res.send('操作成功')
})
app.listen(1000)
- 全局中间件中设置的req参数,可以在所有路由中获取,
- 局部中间件中设置的req参数,只能在使用局部中间件的路由中获取
- 在路由中只能获取req参数,不能设置参数,设置也不生效
6.2.3 同时使用多个局部中间件
const express = require('express')
const app = express()
fun1 = (req, res, next)=> {
// ...
next()
}
fun2 = (req, res, next)=> {
// ...
next()
}
fun3 = (req, res, next)=> {
// ...
next()
}
app.get('/list', fun1, fun2, fun3, (req, res)=> {
// ....
})
app.listen(1000)
6.3 中间件的作用
多个中间件见,共享同样的req和res
,我们可以给req和res
添加方法和属性,给下面的中间件或者路由使用,使代码更优雅
6.4 中间件分类
应用级别
的中间件路由级别
的中间件错误级别
的中间件Express内置
的中间件第三方
的中间件
6.4.1 应用级别中间件
通过app.use
,app.get()
,app.post()
绑定到app
实例上的中间件
6.4.2 路由级别中间件
通过Router.use()
,Router.get()
,Router.post()
绑定到Router
实例上的中间件
const express = require('express')
const Router = express.Router()
Router.use((req, res, next)=>{
// ....
next()
})
Router.get('/list', fun1, (req, res)=>{
// ....
})
module.exports = Router
6.4.3 错误级别中间件
专门用来捕获异常,格式:处理函数有4个形参,分别是err
,req
,res
,next
app.get('/list', (req, res)=> {
throw new Error('抛出一个错误')
res.send('请求成功')
})
app.use((err, req, res, next)=>{
console.log('发送错误 ' + err。message)
res.send('Erroe!' + err.message)
})
错误中间件必须注册在所有路由之后
6.4.4 内置中间件
express.static()
托管静态资源
app.use(express.static('./public'))
express.json()
post解析json请求体数据
app.use(express.json())
express.urlencodeed()
解析URL-encoded格式的请求体数据
app.use(express.urlencoded({ extended: false }))
7 cors中间件解决跨域问题
- 运行
npm install cors
安装中间件 - 使用
const cors = require('cors')
导入中间件 - 在路由之前调用
app.use(cors())
配置中间件
const express = require('express')
const cors = reqiure(''cors)
const app = express()
app.use(cors())
7.1 CORS响应头
- Assess-Control-Allow-Origin 哪些URL可以访问
Assess-Control-Allow-Origin: origin | *
- origin - 指定允许访问的URL
- *-----通配符 ,所有的URL都能访问
res.setHeader('Assess-Control-Allow-Origin': '*')
- Assess-Control-Allow-Headers 对格外的请求头进行申明
res.setHeader('Assess-Control-Allow-Headers', 'xxxxx')
- Assess-Control-Allow-Methods 指定允许客户端发起的请求方式(get,post,put,delete)
res.setHeader('Assess-Control-Allow-Methods', 'POST, GET, DELETE, PUT')
res.setHeader('Assess-Control-Allow-Methods', '*')
7.2 简单请求
- 请求方式只能是
GET
POST
HEAD
- 请求头不包含自定义请求头
满足以上条件才为简单请求
7.3 预检请求
- 请求方式为
GET
POST
HEAD
以外的 - 请求头包含自定义请求
- 想服务器发送了
application/json
格式的数据
满足上面一个条件即为预检请求
在 浏览器 和 服务器正式通信之前, 浏览器会先发送一个 OPTION
请求进行预检, 以获知服务器是否允许该请求。所以称此次请求为“”预检请求“,服务器成功相应预检请求后,才会发送真正的请求,并携带真实参数。