第三方Express 路由和路由中间件

文章目录


1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。

  1. Request 对象
    request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性

    属性/方法 说明
    app 当callback为外部文件时,用req.app访问express的实例
    baseUrl 获取路由当前安装的URL路径
    body/cookies 获得「请求主体」/ Cookies
    fresh/stale 判断请求是否还「新鲜」
    hostname/ip 获取主机名和IP地址
    originalUrl 获取原始请求URL
    params 获取路由的parameters
    path 获取请求路径
    protocol 获取协议类型
    query 获取URL的查询参数串
    route 获取当前匹配的路由
    subdomains 获取子域名
    accepts() 检查可接受的请求的文档类型
    acceptsCharsets/acceptsEncodings/acceptsLanguages 返回指定字符集的第一个可接受字符编码
    get() 获取指定的HTTP请求头
    is() 判断请求头Content-Type的MIME类型
  2. Response 对象
    response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据

    属性/方法 说明
    app 当callback为外部文件时,用req.app访问express的实例
    append() 追加指定HTTP头
    set() 在res.append()后将重置之前设置的头
    res.cookie(name,value [,option]) 设置Cookie
    opition domain / expires / httpOnly / maxAge / path / secure / signed
    clearCookie() 清除Cookie
    download() 传送指定路径的文件
    get() 返回指定的HTTP头
    json() 传送JSON响应
    jsonp() 传送JSONP响应
    location() 只设置响应的Location HTTP头,不设置状态码或者close response
    redirect() 设置响应的Location HTTP头,并且设置状态码302
    render(view,[locals],callback) 渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
    send() 传送HTTP响应
    sendFile(path [,options] [,fn]) 传送指定路径的文件 -会自动根据文件extension设定Content-Type
    set() 设置HTTP头,传入object可以一次设置多个头
    status() 设置HTTP状态码
    type() 设置Content-Type的MIME类型

2、Express路由

路由是指应用程序的终端节点 (URI) 如何响应客户端请求。

在Express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。

Express中的路由分3部分组成,分别是请求的类型、请求的URL地址、处理函数,格式如下:app.method(path, handler)

1.路由方法

javascript 复制代码
// GET method route
app.get('/', function (req, res) {
  res.send('GET request')
})

// POST method route
app.post('/', function (req, res) {
  res.send('POST request')
})

app.all() 用于在所有 HTTP 请求方法的路径上加载中间件函数。

无论是使用 GET、POST、PUT、DELETE 还是 http 模块中支持的任何其他 HTTP 请求方法,都会对路由 "/secret" 的请求执行以下处理程序。

javascript 复制代码
app.all('/secret', function (req, res, next) {
  console.log('all')
  next() // pass control to the next handler
})

2.路由路径

路由路径可以是字符串、字符串模式或正则表达式。

javascript 复制代码
// acd和abcd
app.get('/ab?cd', function (req, res) {
  res.send('ab?cd')
})




总结:问号前面字符可有可无

javascript 复制代码
app.get('/ab(cd)?e', function (req, res) {
  res.send('ab(cd)?e')
})



总结:问号前面括号内的字符可有可无

javascript 复制代码
app.get('/ab+cd', function (req, res) {
  res.send('ab+cd')
})





总结:加号前面字符可无限叠加

javascript 复制代码
app.get('/ab*cd', function (req, res) {
  res.send('ab*cd')
})



总结:星号前面的字符为开始,后边的字符为结束字符,中间可以任意字符或数字

javascript 复制代码
app.get(/a/, function (req, res) {
  res.send('/a/')
})


总结:满足正则/a/的都满足此方法

javascript 复制代码
app.get(/.*fly$/, function (req, res) {
  res.send('/.*fly$/')
})


总结:满足正则/.*fly$/以fly字符结束的路由

3.路由处理程序

在没有理由继续当前路由时将控制权传递给后续路由。next('route')

路由处理程序可以采用函数、函数数组或两者的组合形式。

  1. 单个回调函数可以处理路由。

    javascript 复制代码
    var express = require('express');
    var app = express();
    app.get('/abc', function (req, res) {
      res.send('hello abc');
    })
    app.listen(8081, function () {
      console.log("服务启动")
    })
  2. 多个回调函数可以处理一个路由(确保指定对象)next();

    javascript 复制代码
    var express = require('express');
    var app = express();
    app.get('/abc', function (req, res, next) {
      console.log(111)
      next()
    }, function(req, res) {
      res.send('hello abc next');
    })
    app.listen(8081, function () {
      console.log("服务启动")
    })	


  3. 回调函数数组可以处理路由。

    javascript 复制代码
    var express = require('express');
    var app = express();
    var a0 = function (req, res, next) {
      console.log('A0')
      next()
    }
    var a1 = function (req, res, next) {
      console.log('A1')
      next()
    }
    var a2 = function (req, res) {
      res.send('Hello from A!')
    }
    app.get('/abc', [a0, a1, a2])
    app.listen(8081, function () {
      console.log("服务启动")
    })


  4. 独立函数和函数数组的组合可以处理路由。

    javascript 复制代码
    var express = require('express');
    var app = express();
    var a1 = function (req, res, next) {
      console.log('A1')
      next()
    }
    var a2 = function (req, res) {
      res.send('Hello from A!')
    }
    app.get('/abc', function (req, res, next) {
      console.log('A0')
      next()
    },[a1, a2])
    app.listen(8081, function () {
      console.log("服务启动")
    })


3. 模块化路由

为了方便对路由进行模块化的管理,Express不建议将路由直接挂载到app上,而是推荐将路由抽离为单独的模块。

将路由抽离为单独模块的步骤如下:

1.创建路由模块对应的.js文件

2.调用express.Router()函数创建路由对象

3.向路由对象上挂载具体的路由

4.使用module.exports向外共享路由对象

5.使用app.use()函数注册路由模块

  1. 创建路由模块

    javascript 复制代码
    // router.js   文件
    var express = require('express'); // 1.导入express
    var router = express.Router();    // 2.创建路由对象
     
    router.get('/login/info', (req, res) => {   // 3.挂载登录用户信息
        res.send('Get user list.');
    });
    router.post('/singUp/add', (req, res) => {   // 4.挂载注册用户的路由
        res.send('Add new user.');
    });
    module.exports = router;  // 5.向外导出路由对象
  2. 注册路由模块

    javascript 复制代码
    const express = require('express');
    const app = express();
    // 1.导入路由模块
    const userRouter = require('./router.js');
    // 2.使用app.use()注册路由模块
    app.use(userRouter);
    app.listen(8081, () => {
        console.log('http://127.0.0.1')
    })
  3. 为路由模块添加前缀

    javascript 复制代码
    // 类似于托管静态资源时,为静态资源统一挂载访问前缀一样
    // 1.导入路由模块
    const userRouter = require('./router.js');
    // 2.使用app.use()注册路由模块,并添加统一的范围前缀 /api 
    app.use('/api', userRouter);

4. Express中间件

1.中间件简介

  1. 中间件简介
    中间件是一种特殊的路由处理函数,它可以在请求到达目标处理函数之前,进行一些预处理操作。Express 支持使用中间件来实现各种功能,例如身份验证、请求日志记录,处理 CORS(跨源资源共享)等。
    注意:中间件函数的形参列表中,必须包含next参数,而路由处理函数中只包含req和res。
    next函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。
    可以使用app.use()连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用

    javascript 复制代码
    const express = require('express');
    const app = express();
    // 一个简单的中间件
    app.use((req, res, next) => {
      console.log(`Request received at ${new Date()}`);
      next(); // 将控制权传递给下一个中间件或路由处理器
    });
    // 一个路由处理器,用于处理 GET 请求
    app.get('/', (req, res) => {
      res.send('Hello, World!');
    });
    
    // 启动服务器
    app.listen(8081, () => {
      console.log('Server is running on port 8081');
    });
  2. 局部中间件
    不使用app.use()定义的中间件,叫做局部生效的中间件, 中间件只在"当前路由中生效",

    javascript 复制代码
    var express = require('express');
    var app = express();
    
    var myLogger = function (req, res, next) {
      console.log('LOGGED')
      next()
    }
    app.get('/', myLogger, function (req, res) {
      res.send('Hello World!')
    })
  3. 中间件的5个使用注意事项

    • 一定要在路由之前注册中间件
    • 客户端发送过来的请求,可以连续调用多个中间件进行处理
    • 执行完中间件的业务代码之后,不要忘记调用next()函数
    • 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
    • 连续调用多个中间件时,多个中间件之间,共享req和res对象
  4. 监听 req 的 data 事件
    在中间件中,需要监听req对象的data事件,来获取客户端发送到服务器的数据。
    如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以data事件可能会触发多次,每一次触发data事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。

    javascript 复制代码
    // 定义变量,用来储存客户端发送过来的请求体数据
    let str = ''
    // 监听 req 对象的 data 事件(客户端发送过来的新的请求体数据)
    req.on('data',(data) => {
      // 打印请求数据
      console.log(data)
    })
  5. 监听 req 的 end 事件
    当请求体数据接收完毕之后,会自动触发req的end 事件。
    可以在req的end 事件中,拿到并处理完整的请求体数据。

    javascript 复制代码
    // 监听 req 对象的 end 事件(请求体发送完毕后自动触发)
    req.on('end',() => {
      // => 打印完整的请求体数据
      console.log(str)
      // TODO: 业务逻辑
      // .......
    })

2.中间件分类

  1. 应用程序级中间件
    通过app.use()或app.get()或 app.post(),绑定到app实例上的中间件,叫做应用级别的中间件,

    javascript 复制代码
    var app = express();
    var myLogger = function (req, res, next) {
      console.log('LOGGED')
      next()
    }
    // 应用级别的中间件(全局中间件)
    app.use((req, res, next) => {
      req.name = 'router'
      req.on('end',() => {
        console.log('end')
      })
      next();
    });
    // 应用级别的中间件(局部中间件)
    app.get('/', myLogger, (req, res) => {
      console.log(req.name)
      res.send('Home page.')
    });
    app.listen(8081, function () {
      console.log("服务启动")
    })
  2. 路由器级中间件
    绑定到express.Router()实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app实例上,路由级别中绚件摸定到router 实例上

    javascript 复制代码
    var express = require('express')
    var app = express()
    var router = express.Router()
    router.use(function (req, res, next) {
      console.log('Time:', Date.now());
      next()
    })
    app.use('/', router)
    app.listen(8081, function () {
      console.log("服务启动")
    })
  3. 错误处理中间件
    错误处理中间件是专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。
    格式:错误级别的中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是(err,req,res,next)。
    注意:错误级别的中间件,必须注册在所有路由之后

    javascript 复制代码
    app.get('/', (req, res) => { // 1.路由
        throw new Error('服务器内部发生了错误');  // 1.1.抛出一个自定义的错误
        res.send('Home Page.');
    });
    app.use((err, req, res, next) => {    // 2.错误级别的中间件
        console.log('发生了错误:' + err.message);   // 2.1.在服务器打印错误消息
        res.send('Erroe!' + err.message); // 2.2.向客户端响应错误相关的内容
    });
  4. 内置中间件
    三个内置的中间件分别是
    express.static 是快速托管静态资源的内置中间件 例如:HTML文件、图片、CSS样式等(无兼容性)
    express.json是拿来解析json格式数据的
    express.urlencoded是拿来解析urlencoded格式数据的

    javascript 复制代码
    var express = require('express');
    var app = express();
    // 注意这是中间件 所以必须配置到路由之前
    app.use(express.json())
    app.use(express.urlencoded({extended : false}))
    app.listen(8081, function () {
      console.log("服务启动")
    })
  5. 第三方中间件
    非Express官方内置的,而是由第三方开发出来的中间件,叫做第三方中间件。在项目中,大家可以按需下载并配置第三方中间件,从而提高项目的开发效率。
    安装所需功能的 Node.js 模块,然后在应用程序级别或路由器级别将其加载到应用程序中。
    以cookie-parser为示例:

    javascript 复制代码
    $ npm install cookie-parser
    javascript 复制代码
    var express = require('express')
    var app = express()
    var cookieParser = require('cookie-parser')
    app.use(cookieParser())

3.自定义中间件

自定义中间件步骤:

  1. 定义中间件

  2. 监听req的data事件

  3. 监听req的end事件

  4. 使用querystring模块解析请求体数据

  5. 将解析出来的数据对象挂载为req.body

  6. 将自定义中间件封装为模块

    javascript 复制代码
    // myparse.js
    //1.1 导入内置模块
    const qs=require('querystring')
    //1.2 编写解析函数
    function myparse(req,res,next){
        //2.2 定义一个变量存储客户端字符串
        let str=''
     
        //2.1 对客户端请求数据的监听
        //注意是对客户端对象进行监听,而不是服务器
        req.on('data',(chunk)=>{
            str+=chunk
        })
     
        //2.4 进行发送数据结束的监听
        req.on('end',()=>{
            //倘若有响应,说明数据发送结束,我们已经拿到所有数据
            console.log(str)
            //4.2 利用内置模块的parser()进行数据解析
            const body=qs.parse(str)
            //4.3 进行数据对象的挂载
            req.body=body
            console.log(body)
        })
    
        //2.5 不要忘记需要调用next函数
        next()
    }
    //1.4 通过module.exports暴露
    module.exports = myparse
    javascript 复制代码
    // 使用
    var express = require('express');
    var app = express();
    // 2.1 导入自定义解析模块
    const myparse = require('./mybody-parse')
    app.use(myparse)
    app.get('/login', function (req, res) {
      console.log(req.body);
      res.end(req.body);
    })
相关推荐
前端小小王27 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发36 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
娃哈哈哈哈呀1 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
ekskef_sef3 小时前
32岁前端干了8年,是继续做前端开发,还是转其它工作
前端
sunshine6413 小时前
【CSS】实现tag选中对钩样式
前端·css·css3
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
蜜獾云4 小时前
npm淘宝镜像
前端·npm·node.js
dz88i84 小时前
修改npm镜像源
前端·npm·node.js
Jiaberrr4 小时前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook