• node.js - 路由、中间件、mysql


    这几天天天搞到这么晚,我看今天的内容看起不多啊,不知道为什么学着学着就到了这么晚。今天的内容还是有点多哈,有点自我矛盾了,再次一一道来。

    1.

    首先今天先看到路由的概念,什么叫做路由?

    路由就是映射关系,在express中路由指的是客户端请求和服务器处理函数的映射关系,路由有三部分组成:请求类型、请求url和处理函数。

    app.get(url,callback)其实就跟我们前面所说的监听事件一样一一样的。

    复制代码
    const express = require('express')
    const app = express()
    app.get('/', (req, res) => {
        res.send('收到get请求')
    })
    app.listen(80, () => console.log('express server running at http://127.0.0.1'))  
    复制代码

    这就是一个最简单的路由。路由的匹配过程,每当一个请求到达服务器器后,需要先经过路由匹配,当请求类型和url匹配成功后才会调用后面的请求函数。、

    用法

    最简单的用法就是像我们上面那样直接挂在实例上,这也是不推荐的,因为一个请求就要挂一个很麻烦很繁琐。

    科学的方法应该是创建路由模块。

    分为五个步骤:

    分别是创建路由js文件、调用express.Router创建路由对象、挂载路由、向外导出路有对象最后我们的入口文件需要导入,在通过app.use去注册

    复制代码
    // 1.导入express
    const express = require('express')
    // 2.创建路由对象
    const router = express.Router()
    // 3.挂载路由
    // 3.1挂载路由获取用户的信息
    router.get('/user/:id', (req,  res) => {
        res.send(req.params)
    })
    // 3.2挂载路由接受用户发送的请求
    router.post('/post', (req, res) => {
        res.send('post成功')
    })
    // 4.向外共享路由成员
    module.exports = {
        express,
        router 
    }
    复制代码
    复制代码
    const express = require('./02模块化路由')
    const app = express.express()
    //  注册路由
    app.use(express.router)
    app.listen(80, () => console.log('express server running at http://127.0.0.1'))
    复制代码

    这里说一下app.use昨天也看到了,他其实就是一个用来注册全局中间件的。然后我们还可以为路由挂载前缀,也是通过app.use来添加方法同昨天基本一样

    2.

    中间件

    指的是业务流程的中间处理环节。

    就是当客户请求到达服务器后,可连续调用多个中间件对这个请求进行预处理,最后通过路由发送出来。

    中间件的本质是一个函数根路有类似但是多了一个参数,next参数。

    next是一个函数它的作用就是实现多个中间件连续调用的关键,把流转关系转给下一个中间件或者路由,每个中间件都有一个next一个转下去转到路由没有了就响应给客户端了。

    2.1

    我们先看到全局生效的中间件,意思就是客户发起的任何请求,他都会触发,直接通过app.use来注册即可

    复制代码
    const express = require('express')
    const app = express()
    // 中间件
    const mw = function(req, res, next) {
        // res.send('这是中间件环节')
        console.log('这是中渐渐环节')
        next()
    }
    // 通过app。use定义为全局生效的中间件
    app.use(mw)
    
    app.get('/user', (req, res) => {
        res.send('这是get请求')
    })
    
    app.post('/post', (res, req) => {
        res.send('这是一个post请求')
    })
    app.listen(80, () => {
        console.log('http://127.0.0.1');
    })
    复制代码

    中间件的作用:

    多个中间件共享同一个res和req,所以可以在上游的中间件定义好这些对象,下游直接用包括路由也可以用

    怎么来定义多个全局中间件,直接通过app.use定义多个即可就像昨天所说的托管静态资源,有多个目录就注册多个

    2.2

    局部中间件

    不是用app.use只对部分的路由有效,路由 的参数规则 也发生了改变

    复制代码
    const express = require('express')
    const app = express()
    
    const mw = function(req, res, next) {
        req.time = Date.now()
        next()
    }
    
    app.get('/', mw, (req, res) => {
        res.send('局部生效' + req.time)
    })
    app.get('/user', (req, res) => res.send('没有生效') + req.time)
    app.listen(80, ()=> {
        console.log('http://127.0.0.1');
    })
    复制代码

    定义多个局部中间件

    写多个函数过后在参数这里可以用逗号隔开,也可以直接写一个数组

    有一个注意事项:就是一定要在路由之前去注册中间件,不然路由执行完了谁还来执行中间件。

    2.3

    中间件的分类

    ①应用级别中间件

    就是通过get、post、use绑定到app上的中间件

    ②路由级别中间件

    就是在我们刚才的路由模块里面来穿插的一个中间件

    ③错误级别中间件

    这个有点说法

    它是专门用来捕获错误信息的而且形参变为了四个

    他也是唯一一个卸载路由后面的中间件

    复制代码
    const express = require('express')
    const { rename } = require('fs')
    const app = express()
    app.get('/', (req, res) => {
        // 1.人为抛出一个错误,一旦有错后面的响应就不会执行了
        throw new Error('服务器内部发生错误')
        res.send('我不能执行出来')
    })
    
    // 2.错误中间件
    app.use((err,req,res,next) => {
        // 2.1向服务器打印错误
        console.log(err.message);
        // 2.2向客户端发送错误
        res.send(err.message)
        // 这样做 好处就是,前面如果发生了错误导致了整个服务器已经崩溃了,什么都执行不了了,这样一来,就可以正常输出错误信息,正常执行后面代码
    })
    app.listen(80, () => console.log('express server running at http://127.0.0.1'))
    复制代码

    ④内置中间件

    三个内置的中间件分别是express.static这个已经说过了前面

    express.json这是拿来解析json格式数据的

    express.urlencoded这是拿来解析urlencoded格式数据的

    后面两个一般会配合req.body来拿请求体数据再给他们拿来解析了

    复制代码
    const express = require('express')
    const app = express()
    // 注意这是中间件 所以必须配置到路由之前
    app.use(express.json())
    app.use(express.urlencoded({extended : false}))
    app.post('/', (req, res) => {
        // 通过req.body可以拿到请求体数据
        // postman在测试的时候选择body里面的raw再把text选择json就可以发送json数据了
        console.log(req.body);
        // 没有解析之前对于json数据是undefined
    })
    
    // 测试urlencoded数据体
    // 这个数据体的格式是x-www-form-urlencoded
    // 固定写法
    app.post('/user', (req, res) => {
        // 没解析前时空对象
        console.log(req.body);
    })
    app.listen(80, () => console.log('express server running at http://127.0.0.1'))
    复制代码

    ⑤第三方中间件 直接npm安装导入通过app.use注册即可使用

    2.4

    自定义中间件

    这里做一个案例自定义一个类似于express.urlencoded功能的中间件可以解析请求体数据

    复制代码
    const express = require('express')
    const app = express()
    // 4.利用node里面的一个内置模块解析请求体数据,在node里面内置了一个querystring模块是专门用来处理查询字符串的,这个模块提供的
    // parse()函数可以把查询字符串转换为对象
    const qs = require('querystring')
    
    // 1.定义中间件
    app.use((req, res, next) => {
    // 2.监听data事件,因为既然是服务器,那么肯定会接收到癞子客户端的请求,如果有时候请求量过大,就会分批次传给服务器数据,所以data事件可能触发多次
    // 就需要把每一次的数据最后拼接起来
    let str = ''
    req.on('data', chunk => {
        str += chunk
    })
    // 3.req的end事件当请求体接收完毕会自动出发end事件可以在这里处理完整的请求体数据
    req.on('end', () => {
        console.log(str);
        str = qs.parse(str)
        console.log(str);
        // 5.讲解洗出来的对象给到req.body
        req.body = str
        next()
    })
    })
    
    
    
    
    app.post('/', (req, res) => {
        res.send(req.body)
    })
    app.listen(80, () => console.log('http://127.0.0.1'))
    复制代码

    然后将自定义中间件进行了一个模块化

    复制代码
    // 4.利用node里面的一个内置模块解析请求体数据,在node里面内置了一个querystring模块是专门用来处理查询字符串的,这个模块提供的
    // parse()函数可以把查询字符串转换为对象
    const qs = require('querystring')
    // 因为别人导入进来是直接注册使用所以可以把app开服务器等一些多余的代码省略就保存app.use里面的
    const bodyParse = (req, res, next) => {
        // 2.监听data事件,因为既然是服务器,那么肯定会接收到癞子客户端的请求,如果有时候请求量过大,就会分批次传给服务器数据,所以data事件可能触发多次
        // 就需要把每一次的数据最后拼接起来
        let str = ''
        req.on('data', chunk => {
            str += chunk
        })
        // 3.req的end事件当请求体接收完毕会自动出发end事件可以在这里处理完整的请求体数据
        req.on('end', () => {
            console.log(str);
            str = qs.parse(str)
            console.log(str);
            // 5.讲解洗出来的对象给到req.body
            req.body = str
            next()
        })
    }
    
    module.exports = bodyParse 
    复制代码
    复制代码
    const bodyParse = require('./自定义中间件模块化')
    const express = require('express')
    const app = express()
    app.use(bodyParse)
    app.post('/', (req, res) => {
        // res.send('收到get请求')
        console.log(req.body);
    })
    app.listen(80, () => console.log('express server running at http://127.0.0.1'))  
    复制代码

    3.

    我们继续看到用express来写接口

    分为了三个步骤

    创建基本服务器、创建 api路由模块、编写get接口

    这是路由模块

    复制代码
    // 2.写api路由模块 就是将路由模块化 因为那边引入进来需要用use来注册同时挂载api前缀
    const  express = require('express')
    const router = express.Router()
    
    
    // 3.编写get接口
    router.get('/get', (req, res) => {
        // 3.1首先拿到用户传过来的数据
        let data = req.query
        // 3.2把数据发送给客户端
        res.send({
            status : 0, // 0表示成功 1表示失败
            msg : 'get请求成功',
            data : data //把数据返回给客户端
        })
    })
    
    // 4.编写post接口
    router.post('/post', (req, res) => {
        // 4.1客户端发过来的数据
        let data = req.body
        res.send({
            status : 0,
            msg :  'post请求成功',
            data : data
        })
    })
    
    module.exports = router
    复制代码

    其实主要就是通过req的那几个属性拿到数据后,再通过send方法发给客户端,下面是入口文件主要就是开启服务器,然后解析下数据

    复制代码
    // 1.创建基本web服务器
    const express = require('express')
    const app = express()
    
    
    // 2.1导入路由模块 并挂载前缀
    const router = require('./router')
    // 4.2注册内置中间件 不然req.body解析不出来 
    app.use(express.urlencoded({extended : false}))
    // 5.cors解决跨域
    const cors = require('cors')
    app.use(cors())
    app.use('/api', router)
    app.listen(80, ()=> {
        console.log('http://127.0.0.1');
    })
    复制代码

    有些东西要把后面看了才知道哈我只是先拿上来了。

    4.

    cors和jsonp

    我们刚才这个案例其实是有bug的,就是有跨域的问题,我们创建一个html文件通过button来获取数据这个时候就会因为协议不同而被同源策略组织。

    我们前面也说过解决跨域一个是cors一个是jsonp,这里肯定不能用jsonp因为他只支持get,那么怎么来用cors呢?

    直接三部曲安装导入加注册就解决了跨域问题了,就这么简单。

    4.1

    什么是cors

    就是由一系列http响应头组成,同源策略碰到这个头就会解除限制。

    cors一般是在服务器进行配置,客户端不需要。

    下面是一些了解性内容

    响应头部:

    第一个res.setHeader(‘Access-Control-Allow-Orign’,‘http:wwwssss。聪明、’)

    这是表示只允许后面这个网站的域来访问,如果为*那就表示允许任何域来访问了

    第二个是前面的基础上为Allow-Headers

    我们的cors默认值只有9个请求头如果超出了这个九个头就必然失败请求,在这个九个之外的可以通过这个代码来添加上来

    第三个前面的基础上-Methods

    cors默认只支持get post head 除此之外的需要用这个来设置。

    4.2

    现在不是了解内容了。

    cors请求分类

    大体上分为简单请求和预检请求。

    什么叫做简单请求

    满足两个条件:

    一个是请求方式在默认的三个之内,一个是http请求头不能超过默认的九个

    什么是预检请求

    三个条件达到其中一种都是

    一个是请求头在九个之外,一个是请求方式在三个之外,还有一个就是发送过来的数据是json数据

    那么他们的区别是什么呢

    很简单,简单请求只会发送一次请求,而预检请求会发送两次请求,为什么?

    因为预检请求会在服务器与客户端正是连接之前,提前发一个option的请求作为预检,看服务器能否跟这个格式的请求相连接,只有请求成功了才会开始正式请求,携带真实数据。

    5.

    今天最后一个内容jsonp接口

    首先要注意一下,如果说已经配置了cors那么必须在配置cors之前去声明jsonp接口,不然会错乱的。

    做这个接口之前我们先来回应一下jsonp的一个知识,首先它是来解决跨域的,我们通过script标签把函数传进来再去调用接口这种方式就叫jsonp

    复制代码
    // 1.创建基本web服务器
    const express = require('express')
    const app = express()
    
    
    // 2.1导入路由模块 并挂载前缀
    const router = require('./router')
    // 4.2注册内置中间件 不然req.body解析不出来 
    app.use(express.urlencoded({extended : false}))
    // 6.jsonp接口必须写在coes之前
    app.get('/api/jsonp', (req, res) => {
        // 6.1获取回调函数的名字
        let fn = req.query.callback
        // 6.2定义你要发送回去的数据对象
        let data = {name : '张三', age : 15}
        // 6.3模拟函数调用
        let fnDiao = `${fn}(${JSON.stringify(data)})`
        // 6.4数据返回回去
        res.send(fnDiao)
    })
    // 5.cors解决跨域
    const cors = require('cors')
    const { json } = require('body-parser')
    app.use(cors())
    app.use('/api', router)
    app.listen(80, ()=> {
        console.log('http://127.0.0.1');
    })
    复制代码

     

     


    __EOF__

  • 本文作者: Heymar
  • 本文链接: https://www.cnblogs.com/heymar/p/16146689.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    HTML静态网页作业——基于html+css+javascript+jquery+bootstarp响应式成都家乡介绍网页
    Vue学习:理解数据代理
    【藏经阁一起读】(69)__《阿里云视频云产品手册2023版》
    鸿蒙Harmony应用开发—ArkTS声明式开发(触摸事件)
    基因组组装---Nanopore数据评估(nanoqc和NanoPlot)
    react redux demo
    Allegro基本规则设置指导书之Same Net Spacing规则设置
    Spark大数据分析与实战笔记(第一章 Scala语言基础-5)
    1.7.C++项目:仿muduo库实现并发服务器之Poller模块的设计
    一本非专业应届生成功斩获华为22k OFFER,如何实现
  • 原文地址:https://www.cnblogs.com/heymar/p/16146689.html