在 NestJS 中,Reflector@SetMetadata 是一对常用的工具,用于在运行时管理和提取元数据。这些元数据可以用于各种场景,如权限控制、日志记录、缓存策略等。下面详细介绍它们的用法和结合示例。

1. @SetMetadata

@SetMetadata 是一个装饰器,用于在类、方法或其他装饰器上设置键值对形式的元数据。它通常用于定义一些配置信息,这些信息可以在运行时通过 Reflector 提取。

语法

@SetMetadata(key: string, value: any)
  • key: 元数据的键。
  • value: 元数据的值,可以是任何类型。

示例

假设我们要定义一个角色元数据,用于权限控制:

直接在控制器前使用

@SetMetadata('role', ['admin'])
  @UseGuards(PersonGuard)
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.personService.findOne(+id);
  }

可以使用,但每个都使用@SetMetadata不够优雅,一般使用自定义装饰器:

nest g d roles

import { SetMetadata } from '@nestjs/common';

export const ROLES_KEY = 'roles';
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);

在controller中直接使用自定义装饰器


//@SetMetadata('role', ['admin'])
  @Roles('admin')
  @UseGuards(PersonGuard)
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.personService.findOne(+id);
  }

2. Reflector

Reflector 是一个服务,用于在运行时提取通过 @SetMetadata 设置的元数据。它通常在守卫(Guards)、拦截器(Interceptors)、管道(Pipes)等地方使用。

导入 Reflector

import { Reflector } from '@nestjs/core';

使用 Reflector

Reflector 提供了多个方法来提取元数据,常用的有:

  • get<T>(metadataKey: string, target: object): T: 从目标对象(类或方法)中获取指定键的元数据。
  • getAllAndOverride<T>(metadataKey: string, context: ExecutionContext): T: 从执行上下文中获取并覆盖指定键的元数据。
  • getAllAndMerge<T>(metadataKey: string, context: ExecutionContext): T: 从执行上下文中获取并合并指定键的元数据。

示例

假设我们要创建一个 PersonGuard 守卫,用于检查用户是否有访问特定路由的权限:

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

@Injectable()
export class PersonGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!requiredRoles) {
      return true; // 如果没有设置角色要求,则允许访问
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user; // 假设用户信息存储在请求对象中

    if (!user || !user.roles) {
      return false; // 如果用户没有角色信息,则拒绝访问
    }

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

3. 总结

  • @SetMetadata: 用于在类、方法或其他装饰器上设置键值对形式的元数据。
  • Reflector: 用于在运行时提取通过 @SetMetadata 设置的元数据,常用于守卫、拦截器、管道等场景。

通过结合使用 @SetMetadataReflector,你可以在 NestJS 中实现灵活且可配置的逻辑,如权限控制、日志记录、缓存策略等。

最后修改:2025 年 03 月 07 日
如果觉得我的文章对你有用,请随意赞赏