中间件(Middleware),特指业务流程的中间处理环节。我们可以把中间件比作工厂中的车间。比如:在处理铁矿石的时候,一般都要经过三个处理环节,从而保证处理过后的矿石达到标准的钢材。处理铁矿石的这三个中间处理环节,就可以叫做中间件。而中间件其实是路由的升级,也能达到请求的匹配,只不过必须要进行下一步处理,以到达最终的路由匹配,就像在工厂中生产产品,最后必须要出厂。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4roAsMWt-1635505479755)(img\3-5中间件原理-炼钢车间.png)]
效率高、中间件可以重复使用。
底层都是函数 。
当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。但是必须要有一个最终的匹配路由进行响应给客户端结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2iRMU3MU-1635505479758)(img\3-6程序中的中间件执行流程.png)]
app.use( [前缀,]callback )//自定义中间件
callback( req,res,next )
app.use( function(req,res,next){ //next: 下一步
//res.send('无论什么请求:get/post/delete/put 以及无论什么路径都会匹配这个函数'),因此不能在这写send
let d = new Date()
let year = d.getFullYear()
let month = d.getMonth() + 1
let day = d.getDate()
let h = d.getHours()
let m = d.getMinutes()
let s = d.getSeconds()
req.time = ` ${year}年${month}月${day}日 ${h}:${m}:${s}`//在中间件写公共变量写在req里,所有路由都拿到这个变量。
next() //去找最终的匹配路由
} )
app.get('/login',(req,res)=>{
res.send('login page,登录时间为:' +req.time)
})
// /register : 用户注册的 。注册时间
app.get('/register',(req,res)=>{
res.send('register page,注册时间为:' + req.time)
})
app.get('/demo',(req,res)=>{
res.send('demo page,时间为:' + req.time)
})
//只以 /login 开头的都会匹配上此中间件
//例如: /login 肯定匹配 /login/aaa 匹配 /register不能匹配.
app.use( '/login',function(req,res,next){ //next 下一步
console.log('中间件1')
req.times = '我是时间:2021'
next() //去找最终的匹配路由
} )
app.get('/login',(req,res)=>{
res.send('login ' + req.times)
})
app.get('/login/aaa',(req,res)=>{
res.send('login ' + req.times)
})
// /register不会匹配。
app.get('/register',(req,res)=>{
res.send('register ' + req.times)
})
app.js
//引入对应的老师路由模块
const teacherRouter = require('./router/teacher.js')
app.use( '/teacher',teacherRouter )
teacher.js
//编写学生的功能路由
//1. 先引入express
const express = require('express')
//2. 实例化路由对象
const router = express.Router() //返回一个 路由 函数
router.get('/add',(req,res)=>{
res.send('添加老师')
})
router.get('/delete',(req,res)=>{
res.send('删除老师')
})
router.get('/edit',(req,res)=>{
res.send('编辑老师')
})
router.get('/views',(req,res)=>{
res.send('查看老师')
})
//3. 暴露路由函数
module.exports = router
访问:http://localhost:3000/teacher/add
app.get
app.post
//express 自带了404错误,但是不太好看
app.get('/login',(req,res)=>{
res.send('login')
})
app.get('/register',(req,res)=>{
res.send('register')
})
//404中间件,还是自定义中间的一种特殊形式而已,就是放在所有路由的最后面。
app.use( (req,res)=>{
//按照http协议规范,你访问不存在的页面,后端应该返回404错误
res.status( 404 ) //设置状态码的方法,除了200以外的状态码需要手动设置
// res.send('mys is 404 page')
res.sendFile( path.join( __dirname,'views/404.html' ) )
})
统一数据处理。
app.get('/login',(req,res,next)=>{
next('111') //就找后面的app.use( callback(err,req,res,next) )
//如果后面没有err参数的中间件,则直接输出next的参数在页面上,类似res.send.
//next的参数 由err参数接收
}
app.use( (err,req,res,next)=>{
res.send(err); //111
})
//定义登录
app.get('/login',(req,res,next)=>{
let { username = '',password = '' } = req.query
//验证数据是否正确
//1. 用户名不能为空
if( !username ){
next('用户名不能为空')
return
}
//2. 密码不能为空
if( !password ){
next('密码不能为空')
return
}
next('实现登录')
})
//错误的都放在最后面。这个中间件也是自定义中间件,但回调函数必须是4个参数 。
//如何才能匹配上这个路由:在前面路由中 调用next函数,next必须传递一参数 。
app.use( (err,req,res,next)=>{
// res.send('到达了4个参数的这个中间件')
res.send( ` ${err} ` )
} )
指的是express框架中自带的中间件函数 。
img、css、前端特效的js、各种各样的字体文件、视频、音频。
html文件 不是静态资源,因为html它需要设置【定义】独立的路由。
开放静态资源:项目中的静态资源可以通过 url地址访问的。
app.use ( '/官方推荐加上前缀' , express.static( '要开放的文件夹地址' ) )
app.js例:
app.use( '/static',express.static( './static' ) )
//这不是错误的中间件,所以放在前面
//不写第一个路径参数则开放在根目录,即地址为localhost:3000/images/erha1.jpg
html例:
<body>
<h1>我是小U课堂的首页h1>
<h2>可能有图片h2>
<img src="/static/images/erha1.jpg" width="200" alt="">
<img src="/static/images/erha2.jpg" width="200" alt="">
<h3>可能有css引入h3>
<h4>可能引入前面jsh4>
<script src="/static/js/aa.js">script>
body>
app.use(express.urlencoded({extended:false}))
前端的表单提交用post时,默认会设置enctype=“application/x-www-form-urlencoded”。
<form action="/路径" >
默认会设置以下请求头字段:
Content-Type:application/x-www-form-urlencoded
key1=valu1&key2=value2... //并且传递的参数会自动设置成查询字段参数
//后端在最前面加上以上中间件以后,使用req.body接收传递过来的参数。
req.body//返回一个对象
app.use( express.json() )
ajax设置以下请求头字段:
POST {{url}}/login
Content-Type: application/json
{"username":"zs111","password":"123"}
//后端在最前面加上以上中间件以后,使用req.body接收传递过来的参数。
req.body
1. 下载
2. 引入
const 第三方中间件 = require (包名)
3. 使用中间件。这一步需要看手册,有的需要使用app.use(),有的不用。
app.use( 第三方中间件(相对地址) )
例:小图标 serve-favicon
const serveFavicon = require('serve-favicon')
//需要用app.use();而fromidable则不需要。
app.use(serveFavicon('./favicon.ico'))
1.使用url传递参数有大小限制。因为get只能通过url传递参数
2.post没有大小限制
3.post是通过请求体传递的参数
svg-captcha
uire (包名)
例:小图标 serve-favicon
```js
const serveFavicon = require('serve-favicon')
//需要用app.use();而fromidable则不需要。
app.use(serveFavicon('./favicon.ico'))
1.使用url传递参数有大小限制。因为get只能通过url传递参数
2.post没有大小限制
3.post是通过请求体传递的参数
svg-captcha