目录
express的基本使用
一、获取URL中携带的查询参数
app.get('/',(req,res) =>{
// req.query 默认是个空对象
//客户端判断 ?name=zs&age=20 这种查询字符串,发送到服务器的参数
// 可以通过 req.query 对象访问到
// eg : req.query.name req.query.age
console.log(req.query)
})
二、获取URL中的 动态参数
app.get('/user/:id' , (req,res) =>{
// 里面存放着通过 : 动态 匹配到的参数值
console.log(req.params)
})
三、 express.static() 托管静态资源
const express = require('express')
const app =express()
app.use(express.static('./clock'))
app.listen(3000,()=>{
console.log( '服务器已在成功启动 http://localhost:3000');
})
挂载路径前缀
app.use('/public',express.static('./clock') )
路由的使用
express路由使用
const express = require('express')
const app = express()
app.get('/', (req,res)=>{
res.send('hello get')
})
app.post('/', (req,res)=>{
res.send('hello post')
})
app.listen(80, ()=>{
console.log('http://localhost:80');
})
模块化路由
const express = require('express')
const app = express()
const router =require('./04-router.js')
app.use(router)
app.listen(80, ()=>{
console.log('http://localhost:80');
})
路由模板
const 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
为路由模块添加前缀
const userRouter = require('./rouetr/user.js')
app.usre('/api', userRouter)
express 中间件
全局中间件
app.use((req,res,next)=>{
console.log('js是世界上最好de语音');
next()
})
app.get('/',(req,res)=>{
res.send('home page')
})
app.get('/user',(req,res)=>{
res.send('user page')
})
局部中间件
const mw =(req,res,next)=>{
console.log('js是世界上最美丽的语音');
next()
}
app.get('/',mw,(req,res)=>{
res.send('home page')
})
局部定义多个中间件
局部中间件 按照从前往后的 顺序执行 多个中间件
app.get('/',[mw1,mw2],(req,res)=>{
res.send('home page')
})
中间件的5个注意事项
- 一定要在路由之前注册中间件
- 客户端发送过来的请求,可以连续调用多个中间件进行处理
- 执行完中间件的业务代码之后,不要忘记调用next()函数
- 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
- 连续调用多个中间件时,多个中间件之间,共享req和res 对象
中间件的分类
应用级别的中间件
通过 app.use()或app.get(),app.post() 绑定到 app 实例上的中间件 都叫应用级别的中间件
路由级别的中间件
错误级别的中间件
格式 : 错误级别中间件的function 处理函数中 ,必须有有4个形参,顺序分别是(err,req,res,next)
const express = require('express')
const app = express()
app.get('/',(req,res)=>{
throw new Error('服务器内部发生了错误')
res.send('')
})
app.use((err,req,res,next)=>{
console.log('发生了错误' +err.messsage);
res.send('Error'+err.message)
})
app.listen(3000, ()=>{
console.log('http://localhost:3000');
})
Express内置的中间件
- express.static 快速托管静态 资源的内置中间件
- express.json 解析JSON 格式请求体 (4.16版本)
- express.urlencoded 解析URL-encoded 格式的请求体数据
application/json 数据格式 {"title":"test","sub":[1,2,3]} 的方式进行编码
application/x-www-form-urlencoded 数据格式 **key1=val1&key2=val2 **
具体两者 关系前往 Express中间件
第三方中间件
-
body-parser
- npm install body-parser
- require 导入中间件
- app.use()注册 使用中间件
Express 内置的 express.urlencoded 中间件 基于 body-parser 第三方中间件 进一步封装出来的
const express = require('express') const parser = require('body-parser') const app = express() app.use(parser.urlencoded({extended:false})) app.post('/user',(req,res)=>{ res.send('hello my friend') console.log(req.body); }) app.listen(3000, ()=>{ console.log('http://localhost:3000'); })
自定义中间件
- 手动模拟一个 express.urlencoded 解析 POST 提交到服务器表单
- 定义中间件
- 监听req 的data 事件
- 使用 querystring 模块 解析请求体 数据
- 讲解析出来的数据 对象 挂载为 res.body
- 讲自定义中间件封装为模块
const express = require('express')
const app = express()
const qs =require('querystring')
//调用 querystring.parse() 可将字符串转换成 对象的形式
// json.stringgify() 可将JSON对象 转换成 字符串形式
app.use((req,res,next)=>{
let str=''
req.on('data',(chunk)=>{ //监听data 事件 将每次传输的数据 拼接
str += chunk
})
req.on('end',()=>{
const body=qs.parse(str)
req.body=body
next()
})
})
app.post('/user', (req,res)=>{
res.send(req.body)
})
app.listen(3000, ()=>{
console.log('http://localhost:3000');
})
自定义中间件的封装
const express = require('express')
const custombodyparser = require('./11.custombodyparser')
//调用封装的函数 对数据进行格式
const app = express()
app.use(custombodyparser)
app.post('/user', (req,res)=>{
res.send(req.body)
})
app.listen(3000, ()=>{
console.log('http://localhost:3000');
})
const qs =require('querystring')
const custombodyparser= (req,res,next)=>{
let str=''
req.on('data',(chunk)=>{
str += chunk
})
req.on('end',()=>{
const body=qs.parse(str)
req.body=body
next()
})
}
module.exports= custombodyparser
使用Express 写接口
-
创建基本的服务器
-
创建API路由模块
-
编写get 接口
-
编写 post 接口
const express =require('express') const router =express.Router() router.get('/get',(req,res)=>{ let query= req.query res.send({ status:0, msg:'get请求成功', data:query }) }) router.post('/post',(req,res)=>{ let body =req.body res.send({ status:0, msg:'post请求成功', data:body }) }) module.exports= router
cors接口跨域问题
接口的跨域问题
- CORS (主流解决方案,推荐使用)
- JSONP (有缺陷 ,只支持GET 请求)
使用CORS 中间件 解决跨域
cors 是Express 的第三方中间件 通过安装 配置 cors 中间件 解决跨域问题
- npm i cors
- const cors =require('cors')
- 在路由之前 调用 app.use(cors())
cors中的注意事项(1)
- 在路由之前 调用 app.use (cors()) // cors()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="https://cdn.staticfile.org/jquery/1.10.0/jquery.min.js"></script>
<body>
<button id="btnGET">GET</button>
<button id="btnPOST">POSt</button>
</body>
<script>
//get
$('#btnGET').on('click',()=>{
$.ajax({
type:'GET',
url:'http://localhost:3000/api/get',
data:{
name:'zt',
age:20,
gender:'男'
},
success(res){
console.log(res);
}
})
})
//post
$('#btnPOST').on('click',()=>{
$.ajax({
type:'POST',
url:'http://localhost:3000/api/post',
data:{
bookname:'水浒传',
autoname:'施耐庵'
},
success(res){
console.log(res);
}
})
})
</script>
</html>
const express = require('express')
const app = express()
const cors = require('cors')
app.use(cors())
app.use(express.urlencoded({extended:false}))
const apiRouter = require('./13router')
app.use('/api',apiRouter)
app.listen(3000, ()=>{
console.log('http://localhost:3000');
})
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)=>{
let body =req.body
res.send({
status:0,
msg:'post请求成功',
data:body
})
})
module.exports= router
cors中的注意事项(2)
- CORS 主要在服务器端进行配置,客户端无须做任何额外配置,即可请求开启CORS的接口
- CORS 在浏览器中有兼容性
CORS 响应头 Access-Control-Allow-Origin
Access-Control-Allow-Origin: |
eg: res.setHeader('Access-Control-Allow-Origin','itcast.cn') //只允许来自 itcast.cn 的请求
res.setHeader('Access-Control-Allow-Origin', ‘ * ’) //允许任何域 发起请求
回顾jSOP
概念 浏览器 通过script 标签的src 属性 请求服务器上的数据 同时 服务器返回一个函数的调用
这种请求数据的方式 叫做JSONP
特点:
- JSONP 不属于AJAX 请求 因为他没有使用 XMLHTTPRequest 这个对象
- JSONP 仅支持 GET 请求 不支持 POST ,DELETE 等请求
创建JSONP 接口注意事项
如果项目中 已配置CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前 声明JSONP接口,否则
JSONP接口会被处理成开启CORS 的接口
app.get('/api/jsonp',(req,res)=>{})
app.use(cors())
app.get('/api/get',(req,res)=>{})
在网页中使用jquery 发起jsonp 请求
调用$.ajax()函数 ,提供JSONP 的配置选择 从而发起JSONP请求
$('#btnJSONP').on('click',()=>{
$.ajax({
method:'GET',
url:'http://localhost:3000/api/jsonp',
dataType:'jsonp', //很关键
success(){
console.log(res)
}
})
})
app.get('/api/jsonp',(req,res)=>{
const funcName =req.query.callback
const data = { name : 'zs' , age: 22 }
const scriptStr = `${funcName}(${JSON.stringify(data)})` //返回来调用 cb(data)
res.send(scriptStr)
})