NestJS 主要组件详解

NestJS 主要组件详解(开发者视角)

// ---------- 模块(Module)示例 ----------
// 模块是组织代码的核心单元,用于聚合相关功能
@Module({
  imports: [DatabaseModule, AuthModule],  // 导入其他模块
  controllers: [UserController],         // 注册控制器
  providers: [UserService, Logger]       // 注册服务/提供者
})
export class UserModule {}

​使用建议​​:

  1. 按业务领域划分模块(用户/订单/商品)
  2. 核心模块通过静态 register/forRoot 方法暴露配置
  3. 共享模块使用 exports 暴露公共组件
    ​注意​​:避免循环依赖,使用 forwardRef() 处理模块间相互引用
// ---------- 控制器(Controller)示例 ----------
@Controller('users')
export class UserController {
  constructor(private userService: UserService) {}  // 依赖注入

  @Get(':id')
  @HttpCode(206)  // 自定义状态码
  async getUser(@Param('id') id: string) {
    return this.userService.findUser(id);
  }

  @Post()
  @Header('Cache-Control', 'none')
  createUser(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }
}

​使用建议​​:

  1. 保持控制器纤薄,仅处理 HTTP 相关逻辑
  2. 使用装饰器处理请求参数(@Query/@Body/@Headers)
  3. 复杂路由配置使用@Render/@Redirect
    ​注意​​:避免在控制器中直接操作数据库,交由 Service 处理
// ---------- 服务(Service)示例 ----------
@Injectable()
export class UserService {
  private cache = new Map<string, User>();

  constructor(@Inject('Logger') private logger: Logger) {}

  async findUser(id: string): Promise<User> {
    this.logger.log(`查询用户 ${id}`);
    return this.cache.get(id) || { id, name: '默认用户' };
  }
}

​使用建议​​:

  1. 使用 @Injectable() 声明可注入类
  2. 通过 constructor 注入依赖项
  3. 复杂业务实现领域驱动设计(DDD)
    ​注意​​:服务应保持无状态,避免在实例中存储请求级数据
// ---------- 中间件(Middleware)示例 ----------
export class AuthMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const token = req.headers['authorization'];
    if (!validateToken(token)) {
      throw new UnauthorizedException('无效令牌');
    }
    next();  // 必须调用 next() 继续执行
  }
}

// 模块中配置
@Module({
  // ...
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(AuthMiddleware)
      .exclude('public/*')  // 排除特定路由
      .forRoutes('*');      // 应用到所有路由
  }
}

​使用建议​​:

  1. 处理跨域、日志、请求预处理等通用逻辑
  2. 使用 exclude() 跳过不需要处理的路径
  3. 多个中间件使用 apply(m1, m2).forRoutes()
    ​注意​​:Express 中间件需要适配器,Fastify 需要转换写法
// ---------- 管道(Pipe)示例 ----------
@Injectable()
export class ValidationPipe implements PipeTransform {
  constructor(private schema: Joi.Schema) {}

  transform(value: any) {
    const { error } = this.schema.validate(value);
    if (error) {
      throw new BadRequestException('参数校验失败');
    }
    return value;
  }
}

// 使用方式:
@Post()
createUser(@Body(new ValidationPipe(createUserSchema)) dto: CreateUserDto) {
  // ...
}

​使用建议​​:

  1. 优先使用内置 ValidationPipe + class-validator
  2. 自定义管道处理类型转换(字符串转日期/数字)
  3. 全局管道可统一校验规则
    ​注意​​:管道抛出异常会被异常过滤器捕获
// ---------- 守卫(Guard)示例 ----------
@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = ['admin'];
    const user = context.switchToHttp().getRequest().user;
    return requiredRoles.some(role => user.roles.includes(role));
  }
}

// 控制器使用:
@UseGuards(RolesGuard)
@Get('admin')
getAdminData() { ... }

​使用建议​​:

  1. 结合 JWT 策略实现 RBAC 权限控制
  2. 使用反射元数据存储权限信息(@SetMetadata)
  3. 全局守卫处理通用鉴权逻辑
    ​注意​​:守卫抛出异常会直接终止请求链

// ---------- 拦截器(Interceptor)示例 ----------
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      map(data => ({ 
        code: 200,
        data,
        timestamp: new Date().toISOString()
      }))
    );
  }
}

// 全局注册(main.ts)
app.useGlobalInterceptors(new TransformInterceptor());

​使用建议​​:

  1. 统一响应格式
  2. 记录请求耗时(console.time/timeEnd)
  3. 缓存请求结果
    ​注意​​:拦截器可以修改响应但无法修改请求头

实际开发注意事项

  1. ​依赖注入顺序​​:
    模块初始化顺序影响依赖可用性,使用 @Global() 定义全局模块

  2. ​请求作用域​​:
    需要请求级实例时使用 scope: Scope.REQUEST,注意性能影响

  3. ​配置管理​​:
    使用 @nestjs/config 加载环境变量,避免硬编码

  4. ​异常处理优先级​​:
    过滤器的捕获顺序:控制器方法 > 控制器类 > 全局

  5. ​性能优化​​:

  • 开启 FastifyAdapter 提升吞吐量
  • 使用 CacheInterceptor 缓存高频请求
  • 避免在循环中实例化服务
// 最佳实践示例:完整的用户模块结构
// user/
//   ├── dto/
//   │    ├── create-user.dto.ts
//   │    └── update-user.dto.ts
//   ├── entities/
//   │    └── user.entity.ts
//   ├── user.controller.ts
//   ├── user.service.ts
//   └── user.module.ts

通过合理组织代码结构,结合装饰器的声明式编程,可以显著提升 NestJS 项目的可维护性。

建议采用分层架构,区分 presentation layer(控制器)、business logic layer(服务)、data access layer(仓库模式),同时利用拦截器/过滤器等横向关注点处理机制保持代码整洁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值