第六章 AOP架构 Middleware、Guard、Pipe、Interceptor、ExceptionFilter

Nest AOP 是指在 Nest.js 框架中使用面向切面编程(Aspect-Oriented Programming)的技术。面向切面编程是一种编程范式,它允许开发者通过在代码中定义切面(Aspect),来将横切关注点(Cross-cutting Concerns)与核心业务逻辑进行解耦。

在 Nest.js 中,开发者可以使用 Nest AOP 模块来实现 AOP 功能。通过使用装饰器(Decorator)来定义切面,并使用注入依赖(Dependency Injection)来实现对切面的使用。Nest AOP 提供了一系列的装饰器和注解,开发者可以使用它们来在不修改原有代码的情况下,为应用程序的不同部分添加额外的行为。
使用 Nest AOP,开发者可以很方便地实现一些跟业务逻辑无关但又必要的功能,比如日志记录、性能监控、缓存等。同时,它也能提高代码的可维护性和可测试性,使应用程序更易于理解和扩展。
当请求过来,可能会经过 Controller(控制器)、Service(服务)、Repository(数据库访问) 的逻辑

当我们想在这些逻辑里加入一些通用逻辑该怎么加呢?
可能我们会直接想到在哪用到就在哪里增加代码,但是这样会造成通用的逻辑入侵到了业务代码里面,所以AOP (面向切面编程) 孕育而生,它的作用是一些通用逻辑分离到切面中,保持业务逻辑的纯粹性,这样切面逻辑可以复用,还可以动态的增删。
例如下图:

Nest 实现 AOP 的方式更多,一共有五种,包括 Middleware、Guard、Pipe、Interceptor、ExceptionFilter。

1、创建项目

首先我们先创建一个项目

nest new aop

1716821071392.png

2、中间件 Middleware

Nest中间件(Middleware)是一种用于处理HTTP请求和响应的中间层。它可以在处理请求之前和之后执行一些操作,例如验证请求、记录日志、处理异常等。

在Nest中,中间件是一个类或函数,它实现了NestMiddleware接口。在类中,可以使用use方法装饰器将该中间件注册到应用程序模块中。在函数中,可以使用@Middleware()装饰器将该中间件注册到相应的路由处理器上。
中间件可以被全局应用或只应用于特定的路由或控制器。全局中间件会应用于应用程序中所有的请求。而特定路由或控制器的中间件只会应用于指定的路由或控制器。

2.1、全局使用

在 main.ts 里通过 app.use 使用:

  app.use(function (req: Request, res: Response, next: NextFunction) {
   
    console.log('之前', req.url);
    next();
    console.log('之后');
  })

1716906053616.png
在 app.controller.ts 中添加

  @Get()
  getHello(): string {
   
    console.log('进入');

    return this.appService.getHello();
  }

1716906148040.png
接着启动项目

pnpm run start:dev

1716821876454.png
浏览器访问 http://localhost:3000/
1716822017496.png
可以看到控制台按照顺序打印出了 之前 进入 之后

这里其实和vue的router路由守卫差不多意思 在进入之前 可以进行一些逻辑判断 接着调用next() 就可进入 接着执行完成里面的内容之后 可以再进行一些操作

1716906176346.png
大家有兴趣可以多建几个接口测试一下 例如

  @Get('www')
  www(): string {
   
    console.log('进入 www');
    return '我调用了www'
  }

1716906561170.png
接着我们游览器打开 http://localhost:3000/www 可以看到控制台
1716906633330.png
这就是全局中间件 Middleware 它可以让我们在调用接口之前 做一些逻辑复用 在处理请求之前和之后执行一些操作

2.1、路由使用

中间件 Middleware除了可以在全局使用 也支持路由中间件

首先 创建一个路由中间件:

nest g middleware log --no-spec --flat

–no-spec 是不生成测试文件 --flat 是平铺,不生成目录
1716907766874.png
可以看到生成以下代码
1716907809302.png
接着我们修改一下 log.middleware.ts

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

@Injectable()
export class LogMiddleware implements NestMiddleware {
   
  use(req: any, res: any, next: () => void) {
   
    console.log('之前', req.url);
    next();
    console.log('之后');
  }
}

并把之前的全局中间件 Middleware 注释掉
1717220250382.png
我们在 app.module.ts 的 AppModule 中 implements NestModule{,在 configure 方法里配置
consumer.apply(LogMiddleware).forRoutes(‘aaa*’);
此处是配置哪些路由生效

import {
    MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import {
    AppController } from './app.controller';
import {
    AppService } from './app.service';
import {
    LogMiddleware } from './log.middleware';

@Module({
   
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
   
  configure(consumer: MiddlewareConsumer) {
   
    consumer.apply(LogMiddleware).forRoutes('www*')
  }
}

接着我们游览器打开 http://localhost:3000/www 可以看到控制台
1717220610552.png
1717220627695.png这就是全局中间件和路由中间件的区别。

3、路由守卫 Guard

NestJS 提供了一种称为 Guard 的路由守卫机制。Guard 可以用于保护路由,只有满足特定条件的请求才能继续执行路由处理程序。 可以用于在调用某个 Controller 之前判断权限,返回 true 或者 false 来决定是否放行

3.1、接口路由守卫

首先我们创建个 Guard:

nest g guard login --no-spec --flat

1717224596828.png
生成如下代码:
1717224647722.png
上面代码实现了CanActivate接口,用于判断用户是否具有激活路由的权限。canActivate方法接收一个ExecutionContext上下文对象作为参数,返回一个布尔值、Promise或Observable,用于表示是否可以激活对应的路由。
我们在代码这加入打印语句 接着把return 返回 false 代表只要调用了这个路由守卫 的接口 都是失败的

import {
    CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import {
    Observable } from 'rxjs';

@Injectable()
export class LoginGuard implements CanActivate {
   
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
   
    console.log('登录 校验');
    return false;
  }
}

接着我们在部分接口 使用 路由守卫 如下代码:(app.controller.ts)


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫ゞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值