热搜:前端 nest neovim nvim

Nest框架中重要内容 => 中间件

lxf2023-06-16 03:10:21

中间件是在路由处理程序 之前 调用的函数

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

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

创建中间件

使用 CLI 创建服务类,只需执行 $ nest g middleware logger 命令

nest g middleware logger

生成中间件文件,如下:

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

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    console.log('触发中间件');
    next();
  }
}

应用中间件

中间件不能在 @Module() 装饰器中列出。

必须使用模块类的 configure() 方法来设置它们。包含中间件的模块必须实现 NestModule 接口。

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserController } from './user/user.controller';
import { UserService } from './user/user.service';
import { UserModule } from './user/user.module';
import { LoggerMiddleware } from './logger/logger.middleware';

@Module({
  imports: [UserModule],
  controllers: [AppController, UserController],
  providers: [AppService, UserService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('user/v3');
  }
}

configure() 方法是 NestJS 中的一个生命周期方法,它实现了 NestModule 接口,用于在模块加载时注册中间件/拦截器/守卫等。该方法会在应用程序启动时自动调用。

apply() 方法是 MiddlewareConsumer 接口中的一个方法,用于将中间件注册到指定的路由上,返回一个 MiddlewareConsumer 实例,可以继续链式调用其他方法。

forRoutes() 方法用于指定中间件要拦截的路由,接收一个对象参数,包含 pathmethod 两个属性,分别表示要拦截的路由路径和请求方法。只有当请求的路径和方法与指定的路由匹配时,中间件才会被触发。

路由是在控制器中使用的,不清楚控制器的同学,可以点击前往学习控制器

// 控制器
import { Controller, Get, Redirect } from '@nestjs/common';
import { AppService } from '../app.service';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
  constructor(
    private readonly appService: AppService,
    private readonly userService: UserService,
  ) {}

  @Get('/v1')
  getRoute() {
    return this.appService.getRoute();
  }
  @Get('/v2')
  @Redirect('/user/v3')
  getName() {
    return this.userService.userName();
  }
  @Get('/v3')
  getAge() {
    return this.userService.getAge();
  }
}

操作一、

因为上方代码中,只拦截user/v3路由,所以访问http://127.0.0.1:3000/user/v3地址,中间件成功拦截并执行中间件中的方法

Nest框架中重要内容 => 中间件

Nest框架中重要内容 => 中间件

操作二、

因为上方代码中,只拦截user/v3路由,所以访问http://127.0.0.1:3000/user/v1地址,中间件不进行拦截,所以终端没有打印 Nest框架中重要内容 => 中间件

Nest框架中重要内容 => 中间件

中间件还可以限制特定的请求方法,例如:

下面的代码中,访问http://127.0.0.1:3000/user/v3地址,中间件只拦截Get请求,其他形式的请求,不进行拦截

import { Controller, Get, Post, Redirect } from '@nestjs/common';
import { AppService } from '../app.service';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
  constructor(
    private readonly appService: AppService,
    private readonly userService: UserService,
  ) {}

  @Get('/v3')
  getAge() {
    return this.userService.getAge();
  }
  @Post('/v3')
  getAge1() {
    return this.userService.getAge();
  }
}

中间件拦截控制器

中间件不仅可以拦截直接定的路由地址,还可以拦截控制器(拦截该控制器中所有请求)

例如:下方代码中,中间件拦截UserController控制器中所有请求

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserController } from './user/user.controller';
import { UserService } from './user/user.service';
import { UserModule } from './user/user.module';
import { LoggerMiddleware } from './logger/logger.middleware';

@Module({
  imports: [UserModule],
  controllers: [AppController, UserController],
  providers: [AppService, UserService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes(UserController);
  }
}

路由通配符

forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });

以上路由地址将匹配 abcd 、 ab_cd 、 abecd 等

中间件消费者(管理中间件)

管理中间件的核心就是MiddlewareConsumer类,提供的几种内置方法来管理中间件。

exclude()方法:表示在exclude方法中的访问地址,不进行拦截,使管理更加灵活

// app.module.ts
import {
  MiddlewareConsumer,
  Module,
  NestModule,
  RequestMethod,
} from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserController } from './user/user.controller';
import { UserService } from './user/user.service';
import { UserModule } from './user/user.module';
import { LoggerMiddleware } from './logger/logger.middleware';

@Module({
  imports: [UserModule],
  controllers: [AppController, UserController],
  providers: [AppService, UserService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .exclude(
        { path: 'user/v1', method: RequestMethod.GET },
        { path: 'user/v2', method: RequestMethod.GET },
      )
      .forRoutes(UserController);
  }
}
// user.controller.ts
import { Controller, Get, Post, Redirect } from '@nestjs/common';
import { AppService } from '../app.service';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
  constructor(
    private readonly appService: AppService,
    private readonly userService: UserService,
  ) {}

  @Get('/v1')
  getRoute() {
    return this.appService.getRoute();
  }
  @Get('/v2')
  getName() {
    return this.userService.userName();
  }
  @Get('/v3')
  getAge() {
    return this.userService.getAge();
  }
  @Post('/v3')
  getAge1() {
    return this.userService.getAge();
  }
}

上方两段代码中,访问user/v1user/v2地址,中间件不拦截;访问user/v3地址,中间件进行拦截

函数式中间件

创建一个函数

// logger.middleware.ts
export function logger(req, res, next) {
 console.log(`Request...`);
 next();
};

注册到apply

// app.module.ts
consumer
  .apply(logger)
  .forRoutes(CatsController);

注意:

中间件没有任何依赖关系时,可以考虑使用函数式中间件

全局中间件

想一次性将中间件绑定到每个注册路由

通过use()方法,在main.ts文件进行注册中间件,这样每次请求都会经过这个中间件

const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!