标题 1 创建基本的服务器
- express的概念
类似于Node.js内置模块中的http模块,专门用来创建web服务器的,官网:http://www.expressjs.com.cn - express能做什么?
主要用于快速、便捷的创建web网站的服务器和API接口的服务器
安装:npm i express@4.17.1
- 创建基本的服务器步骤:
//1.导入express模块
const express=require('express')
//2.创建基本的web服务器
const app=express()
//3.启动服务器
app.listen(80,() => {
consloe.log('http server running at http://127.0.0.1')
})
- 监听get请求和post请求
app.get('/',(req,res) => {
//req是请求对象
//res是响应对象
})
res.send()
把内容响应给客户端;- 通过
req.query
对象,可以访问到客户端通过查询字符串的形式发送给服务器的参数,主要是用于get请求 - 通过
req.body
对象,可以访问到客户端通过JSON格式或者urlencoded格式的形式发送给服务器的参数,主要用于post请求,不是Node.js默认获取参数的方式,是由第三方包body-parse模块提供的。在解析JSON格式和urlencoded格式的时候,要先导入第三方包body-parse,同时也需要配置解析的中间件。
app.use(express.json());//解析JSON格式的中间件
app.use(express.urlencoded({extended:false}));//解析 x-www-form-urlencoded;charset=UTF-8格式的中间件
- 通过 req.params对象,可以访问到URL:冒号后面的动态参数
app.get('/user/:id',(req,res) => {
console.log(req.params);//获取id
})
标题1 Epress路由
- 路由一般情况下作为单独的模块分离出来,也就是路由模块创建单独的.js文件。模块化路由
express.Router()创建的
的实现步骤:
- 单独的.js文件(分离出来的路由模块)
//1.导入express
const express=require('express')
//2.调用exress.Router()函数来创建路由模块
const router=express.Router()
//3.向路由对象上挂载具体的路由
router.get('/user/list',function(req,res) {
res.send('挂载get请求,访问http://127.0.0.1/user/list')
})
router.post('/user/add',function(req,res) {
res.send('挂载POST请求,访问地址http://127.0.0.1/user/add')
//4.利用module.exports对象向外共享路由
module.exports=router
})
- 在创建服务器的文件中注册路由模块
//1.创建基本的服务器
const express=require('express')
const app=express()
//2.导入路由模块
const userRouter=require('./user');//./user是单独的路由模块的.js文件路径
//3.注册路由模块
app.use(userRouter);
//启动web服务器
app.listen(80,() => {
console.log('express server running at http://127.0.0.1')
})
为路由模块添加前缀,如果在路由模块中访问的前缀相同,可以为它们统一添加前缀名称,比如:
app.use('/user',userRouter)
//那么在写路由模块的时候可以省略/user,
router.get('/list',function(req,res) {
res.send('为路由模块统一挂载前缀')
})
//但是在访问的时候,必须加上前缀路径http://127.0.0.1/user/list
标题 express的中间件
- 中间件的本质作用就是,对请求进行预处理,调用的流程就是上一个中间件的输出作为下一个的输入
- 中间件的基本格式,本质就是一个拥有三个形参的function函数,分别是req、res、
next
,示例代码如下:
next是一个函数,是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或者路由。
- 局部中间件
只在当前路由中生效
const mw1=(req,res,next) {
console.log('调用了局部生效的中间件')
next()
}
app.get('/',mw,function(req,res) {
res.send('home page')
})
定义多个局部中间件,路由的请求参数2,用数组来包裹中间件的名称或者多个中间件之间用逗号隔开app.get('/',[mw1,mw2],...)或者app.get('/',mw1,mw2)
- 全局生效的中间件
app.use(中间件函数)
const mw=function(req,res,next) {
const time=Date.now()
req.startTime=time;//这个time就可以在请求的时候享用,也就是后面所有的路由响应
next()
}
app.use(mw)
- 中间件的作用
多个中间件之间,共享同一份req和res中的数据,也就是在next()之前定义req或者res数据。定义多个中间件,只需要使用app.use()
连续定义即可
注:中间件必须在路由之前注册;执行中间件的业务代码之后,一定要调用next()函数;为了防止代码逻辑混乱,调用next函数之后就不要写其他代码。
中间件放在最后面注册的话,可以实现页面404的原因是,app.use声明的是全局的中间件,代码是从上向下执行的,其中res.status(404)是让状态码也改变成404
标题 中间件的分类
- 中间件主要分为5大类,分别是:应用级别的中间件、路由级别的中间件、错误级别的中间件、express内置的中间件、第三方的中间件
- 应用级别的中间件:概念:通过
app.use()
或者app.post()
、app.get()
绑定到app实例上的中间件 - 路由级别的中间件:概念:绑定到
express.Router()
实例上的中间件 - 错误级别的中中间件:必须有四个参数,分别是err、req、res、next
一定要注册在所有路由之后
app.use((err,req,res,next) => {
//专门用来捕获整个项目中发生的异常错误
res.send('Error'+err.message);//给客户端响应一些错误内容
})
- Express的内置中间件
快速托管静态资源:app.use(express.static())
解析JSON格式的请求体数据,有兼容性4.16.0+
app.use(express.json())
app.post('/',(req,res) => {
cosnole.log(req.body);
})
在服务器端,可以通过req.body
来获取JSON格式的表单数据和url-encoded格式的数据(以键值对的形式书写)。默认情况下,如果不配置解析表单数据的中间件,则req.body默认等于undefined,返回类型是对象形式的
解析URL-encoded格式的请求体数据,有兼容性4.16.0+
app.use(express.urlencoded({extended:false}))//由body-parser模块分装的
- 第三方中间件使用步骤:
运行npm i 中间件名称 安装中间件body-parser模块
require导入
app.use注册 - 自定义中间件
req对象中的data事件:获取客户端发送的服务器的数据,数据过多的时候,不一定能够发送完整
req对象中的end事件:获取客户端发送到服务器的完整数据
标题 使用EXpress写接口
- 创建基本的服务器
- 创建API路由模块.js
const express=require('expresss')
const router=express.Router()
//在这里挂载具体的路由
router.get('/get',(req,res) => {
//req.query获取客户端通过查询字符串发送到服务器的数据
const query=req.query
res.send({
status:0,
msg:'GET请求成功',
data:query//需要响应给客户端的具体数据
})
//挂载post路由,必须配置解析数据的中间件
router.post('/post',(req,res) => {
const body=req.body
res.send({
status:0,
msg:'post请求成功',
data:body
})
})
})
module.exports=router
在地址栏输入http://127.0.0.1/api/get或者http://127.0.0.1/api/post
3. 导入并注册路由模块
//在路由之前配置解析post路由参数的中间件
app.use(express.urlencoded({extended:false}))
const apiRouter=require('./路由模块的路径.js')
app.use('/api',apiRouter)
标题 CORS解决跨域
- 概念:由一系列HTTP响应头组成,这些HTTP响应头决定浏览器是否阻止前端JavaScript代码获取跨域资源
- 注意点:主要在服务器端进行配置;
- 使用CORS中间件解决跨域问题
使用步骤:
- 使用
npm i cors
安装中间件 - 在路由之前配置cors中间件
const cors=require('cors')
- 在路由之前调用
app.use(cors())
配置中间件
- 响应头部:代码格式:
Access-Control-Allow-Origin:origin
,其中,origin参数的值指定了允许访问该资源的外域,例如
res.setHeader('Access-Control-Allow-Origin','http://itcast.cn')//只允许来自http://itcast.cn访问
//origin的值是*就是允许所有域名的访问
注:如果要配置jsonp接口,必须放在在配置CORS中间件之前
配置JSONP接口
express配置jsonp接口res.jsonp({name:'zs',age:13})
app.get('/api/jsonp',(req,res) => {
//1.得到函数的名称
const funcName=req.query.callback
//2.定义要发送到客户端的数据对象
const data={name:'zs',age:22}
//3.拼接一个函数的调用
const scriptStr=`${funcName}(${JSON.stringify(data)})`
//4.把拼接的字符串,响应给客户端
res.send(scriptStr)
//express中的一句话res.jsonp({返回的数据})等同于上面的四个步骤,也能实现jsonp接口
})
- 简单请求和 预检请求
简单请求满足的条件:请求的方式在GET、POST、HEAD三者之一,请求头不超过那九种
预检请求满足条件:请求方式为GET、POST、HEAD之外的请求类型;请求头种包含自定义头部字段;向服务器发送了application/json格式的数据
预检请求需要请求两次,第一次请求成功才会发生第二次请求
区别:简单请求客户端与服务器只会发生一次请求;预检请求中,客户端与服务器会发生两次请求,OPTION预检请求成功之后,才会发起真正的请求