NestJSAOPBFF

NestJS AOP
& 企业级 BFF

深入理解 NestJS 的面向切面编程五层生命周期,以及如何利用 BFF 模式构建面向前端的后端聚合层, 打造企业级微服务网关。

6AOP 核心层
5生命周期钩子
3BFF 架构模式
Core Concept

请求的「洋葱模型」生命周期

点击每一层查看详细说明。每个请求都会经过这六层处理,像洋葱一样一层层剥开。

🧅 洋葱模型执行顺序

→ Middleware
→ Guard
→ Interceptor (前置)
→ Pipe
→ Controller Handler ◆ 核心
← Interceptor (后置)
← Exception Filter
← 响应发出
Interactive Lab

🛡️ Guard 守卫实验室

模拟不同的请求身份,体验 Guard 如何拦截或放行请求。

roles.guard.tstypescript
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector
      .getAllAndOverride<string[]>('roles', [
        context.getHandler(),
        context.getClass(),
      ]);

    if (!requiredRoles) return true;

    const { user } = context
      .switchToHttp().getRequest();

    return requiredRoles.some(
      (role) => user?.roles?.includes(role)
    );
  }
}

模拟请求身份

请选择一个请求身份…

Decorator Playbook

✨ AOP 装饰器手册

点击装饰器卡片查看代码示例和使用场景。

Deep Dive

⚡ Interceptor 拦截器深度剖析

transform.interceptor.tstypescript
@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>>
{
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> {
    const now = Date.now();

    return next.handle().pipe(
      map(data => ({
        code: 200,
        message: 'success',
        data,
        timestamp: Date.now(),
        duration: `${Date.now() - now}ms`,
      })),
    );
  }
}
logging.interceptor.tstypescript
@Injectable()
export class LoggingInterceptor
  implements NestInterceptor
{
  private readonly logger = new Logger('HTTP');

  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<any> {
    const req = context.switchToHttp().getRequest();
    const { method, url } = req;
    this.logger.log(`→ ${method} ${url}`);

    return next.handle().pipe(
      tap(() => {
        const res = context.switchToHttp().getResponse();
        this.logger.log(
          `← ${method} ${url} ${res.statusCode}`
        );
      }),
    );
  }
}

📊 执行时序图

T0
请求到达

Interceptor.intercept() 被调用

T1
前置逻辑执行

日志记录、计时开始、缓存检查

T2
next.handle()

将控制权交给下一个处理层

T3
Controller 执行

业务逻辑处理、数据库查询

T4
响应数据流回

Observable.pipe(map/tap)

T5
后置逻辑执行

数据转换、响应包装、日志完成

BFF Architecture

🏗️ 企业级 BFF 架构模式

三种主流 BFF 架构策略,点击切换查看详情。

单体 BFF

一个 BFF 服务聚合所有微服务,适合小型项目

优势

  • 部署简单
  • 开发成本低
  • 统一管理

挑战

  • 单点故障
  • 团队协作冲突
  • 技术栈单一
Request Simulation

🔄 完整请求生命周期模拟

模拟一个请求从客户端到服务端的完整 AOP 处理流程。

Step 0/7
客户端请求
API Gateway
BFF 层 (路由/聚合)
Guard (鉴权)
Interceptor (前置)
Pipe (校验转换)
Controller → Service
响应返回客户端
BFF Implementation

🧩 BFF 聚合编排实战

user-bff.controller.tstypescript
@Controller('bff/user')
@UseGuards(AuthGuard)
@UseInterceptors(TransformInterceptor)
export class UserBffController {
  constructor(
    private readonly userClient: ClientProxy,
    private readonly orderClient: ClientProxy,
    private readonly notifyClient: ClientProxy,
  ) {}

  // 聚合多个微服务的数据
  @Get(':id/dashboard')
  async getDashboard(
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    // 并行请求多个微服务
    const [user, orders, notifications] =
      await Promise.all([
        this.userClient
          .send('user.get', { id })
          .toPromise(),
        this.orderClient
          .send('order.recent', { userId: id })
          .toPromise(),
        this.notifyClient
          .send('notification.unread', { userId: id })
          .toPromise(),
      ]);

    // BFF 层的数据编排和裁剪
    return {
      profile: {
        name: user.name,
        avatar: user.avatar,
      },
      recentOrders: orders.slice(0, 5),
      unreadCount: notifications.length,
      quickLinks: this.generateQuickLinks(user.role),
    };
  }
}
bff.module.tstypescript
@Module({
  imports: [
    // 注册微服务客户端
    ClientsModule.register([
      {
        name: 'USER_SERVICE',
        transport: Transport.TCP,
        options: {
          host: 'user-service',
          port: 3001,
        },
      },
      {
        name: 'ORDER_SERVICE',
        transport: Transport.TCP,
        options: {
          host: 'order-service',
          port: 3002,
        },
      },
      {
        name: 'NOTIFY_SERVICE',
        transport: Transport.REDIS,
        options: {
          host: 'redis',
          port: 6379,
        },
      },
    ]),
  ],
  controllers: [UserBffController],
  providers: [
    // 全局 Guard + Interceptor
    {
      provide: APP_GUARD,
      useClass: ThrottlerGuard,
    },
    {
      provide: APP_INTERCEPTOR,
      useClass: CacheInterceptor,
    },
  ],
})
export class BffModule {}

📐 BFF 数据聚合架构图

Web App
Mobile App
小程序
API Gateway

路由 · 限流 · 鉴权 · 日志

BFF 聚合层
GuardInterceptorPipeController
用户服务:3001
订单服务:3002
通知服务:3003
商品服务:3004
Best Practices

🏢 企业级 AOP 最佳实践

统一响应格式

Interceptor

使用 Interceptor 统一包装所有响应为 { code, message, data, timestamp } 格式。前端无需关心后端返回格式差异。

全局异常过滤

Filter

ExceptionFilter 捕获所有异常,区分 HttpException 与未知异常,返回统一错误结构。生产环境隐藏堆栈信息。

声明式权限控制

Guard

自定义 @Roles() 装饰器 + RolesGuard 实现 RBAC。结合 Reflector 读取元数据,实现零侵入的权限管理。

请求链路追踪

Middleware

在 Middleware 中生成 requestId,通过 cls-hooked 注入到请求上下文。贯穿所有 AOP 层和微服务调用链。

接口限流与防刷

Guard

@nestjs/throttler 提供声明式限流。可在 Guard 层按 IP、用户、路由粒度分别配置。配合 Redis 做分布式限流。

缓存策略分层

Interceptor

Interceptor 层实现 HTTP 缓存头管理,Service 层使用 Redis 缓存热点数据。避免在 Controller 层混入缓存逻辑。

Comparison

⚔️ BFF vs GraphQL vs API Gateway

维度
BFF
GraphQL
API Gateway
核心职责
数据聚合裁剪
查询语言 + Schema
路由/限流/鉴权
灵活性
⭐⭐⭐⭐⭐
⭐⭐⭐⭐⭐
⭐⭐⭐
复杂度
中等
端级定制
✅ 天然支持
✅ 查询自选字段
❌ 统一出口
团队要求
全栈能力
Schema 设计能力
运维能力
最佳搭配
+ API Gateway
+ BFF 层
+ BFF 层

企业级推荐架构

API Gateway(Kong/Nginx)负责路由、限流、鉴权 → NestJS BFF(利用 AOP 做数据聚合、裁剪、缓存)→ 微服务集群。三者各司其职,互不耦合。

Cheat Sheet

📋 AOP 核心接口速查

Guard

CanActivate
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean>

返回 true 放行,false 拒绝。支持异步。

Interceptor

NestInterceptor
intercept(context: ExecutionContext, next: CallHandler): Observable<any>

通过 next.handle() 获取 Observable 流,可 pipe 操作。

Pipe

PipeTransform
transform(value: any, metadata: ArgumentMetadata): any

返回转换后的值。抛出异常则阻止请求。

ExceptionFilter

ExceptionFilter
catch(exception: unknown, host: ArgumentsHost): void

通过 host.getResponse() 获取响应对象处理异常。

Middleware

NestMiddleware
use(req: Request, res: Response, next: NextFunction): void

与 Express 中间件相同。必须调用 next()。

ExecutionContext

ExecutionContext
getHandler() / getClass() / getType() / switchToHttp()

可切换到 HTTP/WS/RPC 上下文。Guard 和 Interceptor 的核心参数。

核心要义

🧅NestJS AOP 通过洋葱模型将横切关注点(鉴权、日志、校验、缓存)从业务代码中剥离
🏗️BFF 模式让后端为不同前端量身定制数据聚合策略,避免过度获取或数据不足
🔧自定义装饰器 + Guard/Interceptor 组合实现声明式编程,代码即文档
🚀API Gateway + BFF + 微服务 是企业级架构的黄金三角组合