九、express基于node.js的web开发框架
相比于http创建服务器,提高开发效率
创建web网站的服务器------创建API接口的服务器
安装命令
npm i express@4.17.1
1、创建基本的web服务器
const express = require('express')
const app = express()
//监听客户端的get、post请求,向客户端响应具体的内容
app.get('/user',function(req,res){
//res.send()服务器响应客户端
res.send(
{
name:'zyy',
age:20,
gender:'男'
}
)
})
app.post('/user',function(req,res){
res.send('请求成功')
})
app.listen(80,()=>{
console.log('express server running at http://127.0.0.1');
})
2、res.query() 默认返回是一个空对象,可以携带query参数
res.params()返回的是动态参数
const express = require('express')
const app = express()
//监听客户端的get、post请求,向客户端响应具体的内容
req.get('/',function(req,res){
res.send(res.query)
})
//动态的url参数,params参数 /: 来绑定
app.get('/user/:id',(req,res)=>{
res.send(req.params)
})
app.listen(80,()=>{
console.log('express server running at http://127.0.0.1');
})
2、托管静态资源
express.static()::创建静态资源服务器
//前面的是一个访问前缀,在访问时必须先输入这个前缀
app.use('/public',express.static('./public'))
app.use('/files',express.static('./files'))
3、nodemon使用
代码改变会自动重启服务器-----ctrl+s
npm i -g nodemon
note:安装nodemon之后出现错误,无法运行
解决方法:使用管理员权限打开—powershell
4、express路由
客户端 的请求与服务器处理函数之间的映射关系
请求类型 + path的url + 处理函数
5、模块化路由
将路由抽离为单独的模块::::
创建路由模块对应的.js文件-----调用express.Router()创建路由对象------向路由对象上挂载具体的路由------使用moudle.exports向外共享路由对象-------使用app.use()函数来注册路由模块
为路由添加访问前缀
app.use('/api',router)
6、中间件—对请求进行预处理
函数中的参数多一个next()-------之后会自动匹配到某路由
app.use(mw)::调用了全局生效的中间件
局部生效的中间件:
const mw1 = function(req,res,next){
next()
}
//mw1这个中间件只在访问路由为 / 有影响
app.get('/',mw1,function(req,res){})
7、路由中间使用多个中间件
note:
(1)一定要在路由之前注册中间件,要不事件都响应了,中间件还不执行
(2)可连续调用多个中间件,每个中间都要有next()函数,next函数后不能再跟函数
(3)多个中间件,共享req和res对象
8、中间件分类
应用:直接绑定到app实例上
路由:绑定到express.Router()上
错误:捕获错误的中间件(err,req,res,next)
express内置中间件:express.static、express.json、express.urlencodee
const express = require('express')
var app = express()
const router = express.Router()
//除子错误级别的中间件,其它都在路由之前注册
app.use(router)
app.use(express.json())
app.use(express.urlencoded({extended:false}))
//req.body,可以让服务器获取到客户端传来的数据
app.post('/user/json',(req,res)=>{
console.log(req.body);
res.send('ok')
})
app.post('/user/encode',(req,res)=>{
console.log(req.body);
res.send('ok')
})
app.listen(80,(req,res)=>{
console.log('running at http://127.0.0.1')
})
第三方中间件:body-parser来解析请求体数据
步骤:
npm i body-parser //下载
require //导入中间件
app.use() //注册使用中间件
9、自定义中间件
1、使用querystringify模拟来解析请求体数据
const express = require('express')
const app = express()
const qs = require('querystringify')
//自定义解析表单数据的中间件
app.use((req,res,next)=>{
//req的data:监听req发送来的data,可能不完整,需要多次拼接
let str = ''
req.on('data',(chunk)=>{
str += chunk
})
//req的end事件:end触发代表data发送完毕
req.on('end',()=>{
//todo,把字符串格式的请求体,解析成对象格式的数据
const body = qs.parse(str)
console.log(body)
})
app.post('/user',(req,res)=>{
// console.log(req.body);
res.end('ok')
})
})
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(80, () => console.log(`Example app listening at http://127.0.0.1!`))
2、封装自定义中间件
const qs = require('querystringify')
//自定义解析表单数据的中间件
const bodyParse =
(req,res,next)=>{
//req的data:监听req发送来的data,可能不完整,需要多次拼接
let str = ''
req.on('data',(chunk)=>{
str += chunk
})
//req的end事件:end触发代表data发送完毕
req.on('end',()=>{
//todo,把字符串格式的请求体,解析成对象格式的数据
const body = qs.parse(str)
req.body = body
next()
})
}
module.exports = bodyParse
3、引用自定义中间件
const express = require('express')
const app = express()
const bodyParse = require('./20custom-body-parser')
//注册自定义的中间件,全局可用
app.use(bodyParse)
app.post('/user',(req,res)=>{
console.log(req.body);
res.send(req.body)
})
app.listen(80, () => console.log(`Example app listening at http://127.0.0.1!`))
10、res.end()和res.send()
Express 的 res.end() 和 res.send() 方法的相同点:
- 二者最终都是回归到
http.ServerResponse.Use
的response.end()
方法。 - 二者都会结束当前响应流程。
Express 的 res.end() 和 res.send() 方法的不同点:
- 前者只能发送 string 或者 Buffer 类型,后者可以发送任何类型数据。
- 从语义来看,前者更适合没有任何响应数据的场景,而后者更适合于存在响应数据的场景。
11、express写接口
(1)get接口
(2)post接口
const express = require('express')
const router = express.Router()
//在这里挂载路由
router.get('/get',(req,res)=>{
const query = req.query
res.send({
status:0,
msg:'get请求成功',
data:query
})
})
router.post('/post',(req,res)=>{
//获取客户端通过请求体,发送到服务器的url-encoded数据
const body = req.body
//服务器在客户端调用此接口时,将数据返回给客户端
res.send(
{
status:1,
msg:'post请求成功',
data:body
}
)
})
module.exports = router
12、接口跨域问题
npm i cors
const cors = require('cors')
app.use(cors())
res.setHeaders('Access-Control-Allow-Origin','*')
(1) 使用CORS中间件解决跨域问题--------一定要在路由之前配置,注册使用
CORS是一系列HTTP响应头组成,决定浏览器是否阻止前端JS代码跨域获取资源
在服务器端配置,有兼容性
(2) CORS响应头部
Access-Control-Allow-Origin:允许访问该资源的外域URL
Access-Control-Allow-Headers:有9个指定的请求头,其余的需要指定
Access-Control-Allow-Methods:POST、GET、HEAD,其余的需要指定
(3) JSONP接口
----仅支持get请求
-----前端发送带回调函数的请求,后端处理请求,获取请求名字,并拼接参数返回给前端调用
-----//必须在cors中间件之前,来配置JSONP接口
//必须在cors中间件之前,来配置JSONP接口
app.get('/api/jsonp',(req,res)=>{
//1.定义函数名称
const funName = req.query.callback
//2.定义要发送到客户端的数据
const data = {name:'zyy',age:10}
//3.拼接出函数的调用
const str = `${funName}(${JSON.stringify(data)})`
//4.拼接好的字符串,响应给客户端
res.send(str)
})