node-express中间件

中间件

中间件原理

简介

​ 中间件(Middleware),特指业务流程的中间处理环节。我们可以把中间件比作工厂中的车间。比如:在处理铁矿石的时候,一般都要经过三个处理环节,从而保证处理过后的矿石达到标准的钢材。处理铁矿石的这三个中间处理环节,就可以叫做中间件。而中间件其实是路由的升级,也能达到请求的匹配,只不过必须要进行下一步处理,以到达最终的路由匹配,就像在工厂中生产产品,最后必须要出厂。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4roAsMWt-1635505479755)(img\3-5中间件原理-炼钢车间.png)]

中间件的好处

效率高、中间件可以重复使用。

底层都是函数 。

中间件执行流程

当一个请求到达Express的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。但是必须要有一个最终的匹配路由进行响应给客户端结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2iRMU3MU-1635505479758)(img\3-6程序中的中间件执行流程.png)]

使用中间件

语法

app.use( [前缀,]callback )//自定义中间件
callback( req,res,next )

基本使用

  • 不是处理错误的中间件一律放在所有路由的最前面 。
  • 把中间件公共的数据放到req上。因为每个路由的req对象都是同一个
  • 不能在中间件写send
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/aaa也能匹配上
用法1
//只以 /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)
})

用法2:模块化路由使用中间件

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

自定义中间件

404
//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内置中间件

指的是express框架中自带的中间件函数 。

开放静态资源:static
静态资源 :
  • 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>
接受post参数
  • app.use( express.urlencoded({extended:false}) ) 重点掌握配合表单。
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。
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'))

小结

post与get的一些区别

1.使用url传递参数有大小限制。因为get只能通过url传递参数

2.post没有大小限制

3.post是通过请求体传递的参数

图片验证码 (第三方中间件)

svg-captcha

uire (包名)

  1. 使用中间件。这一步需要看手册,有的需要使用app.use(),有的不用。
    app.use( 第三方中间件(相对地址) )



例:小图标 serve-favicon

```js
const serveFavicon = require('serve-favicon') 
//需要用app.use();而fromidable则不需要。
app.use(serveFavicon('./favicon.ico'))

小结

post与get的一些区别

1.使用url传递参数有大小限制。因为get只能通过url传递参数

2.post没有大小限制

3.post是通过请求体传递的参数

图片验证码 (第三方中间件)

svg-captcha

你可能感兴趣的:(中间件)