NestJs 中间件

https://docs.nestjs.cn/9/middlewares

中间件简介

  • 中间件是在路由处理程序 之前 调用的函数。 中间件函数可以访问请求和响应对象,以及应用程序请求响应周期中的 next() 中间件函数。 next() 中间件函数通常由名为 next 的变量表示。

    图1

    Nest 中间件实际上等价于 express 中间件。 下面是Express官方文档中所述的中间件功能:

    中间件函数可以执行以下任务:

    • 执行任何代码。
    • 对请求和响应对象进行更改。
    • 结束请求-响应周期。
    • 调用堆栈中的下一个中间件函数。
    • 如果当前的中间件函数没有结束请求-响应周期, 它必须调用 next() 将控制传递给下一个中间件函数。否则, 请求将被挂起。

    您可以在函数中或在具有 @Injectable() 装饰器的类中实现自定义 Nest中间件。 这个类应该实现 NestMiddleware 接口, 而函数没有任何特殊的要求。 让我们首先使用类方法实现一个简单的中间件功能。

创建中间件

新建 middlewares文件夹,在此路径下执行下面的命令来创建

nest g mi Login

生成的主要代码

login.middleware.ts

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoginMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    next();
  }
}

image-20230404145627026

要求我们实现use 函数 返回 req res next 参数 如果不调用next 程序将被挂起

实现use 函数

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoginMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    // 假设中间件拦截步骤
    console.log('LoginMiddleware 登录拦截中间件,拦截了:', req.query);
    // 放行
    next();

    console.log('LoginMiddleware 执行结束')
  }
}

image-20230404150050041

中间件注册

注册方法

在模块里面 实现 configure 返回一个消费者 consumer 通过 apply 注册中间件 通过forRoutes 指定 Controller 路由

模块中间件

实现

在对应模块实现

例:p 模块

import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common';
import { PService } from './p.service';
import { PController } from './p.controller';
import { LoginMiddleware } from 'src/middlewares/login/login.middleware';

@Module({
  controllers: [PController],
  providers: [PService]
})

/**
 * 中间件不能在 @Module() 装饰器中列出。
 * 我们必须使用模块类的 configure() 方法来设置它们。
 * 包含中间件的模块必须实现 NestModule 接口。
 * 我们将 LoggerMiddleware 设置在 ApplicationModule 层上。
 */
export class PModule implements NestModule{
  // 在模块里面 实现 configure 返回一个消费者 consumer 
  // 通过 apply 注册中间件 通过forRoutes 指定  Controller 路由
  configure (consumer:MiddlewareConsumer) {
    // 拦截 p 模块
    consumer.apply(LoginMiddleware).forRoutes('p')
    // consumer.apply(LoginMiddleware).forRoutes(PController)
    
    // 拦截 p 模块的get方法
    // consumer.apply(LoginMiddleware).forRoutes({path: 'p', method:RequestMethod.GET})
  }
}

image-20230404152639113

测试

image-20230404152736429

image-20230404152755712

全局中间件

其实全局中间件就是在 根模块 中实现 configure 注册,所谓根模块就是 app.module.ts

主要代码

export class AppModule {
  // 在模块里面 实现 configure 返回一个消费者 consumer 
  // 通过 apply 注册中间件 通过forRoutes 指定  Controller 路由
  configure (consumer:MiddlewareConsumer) {
    // 拦截 p 模块
    consumer.apply(LoginMiddleware).forRoutes('*')
    // consumer.apply(LoginMiddleware).forRoutes(PController)
    
    // 拦截 p 模块的get方法
    // consumer.apply(LoginMiddleware).forRoutes({path: 'p', method:RequestMethod.GET})
  }
}

image-20230404154024816

posted @ 2023-04-04 15:43  makalo  阅读(126)  评论(0编辑  收藏  举报