news 2026/5/13 10:28:32

别再死记硬背了!用这5个真实场景案例,彻底搞懂NestJS装饰器的用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再死记硬背了!用这5个真实场景案例,彻底搞懂NestJS装饰器的用法

别再死记硬背了!用这5个真实场景案例,彻底搞懂NestJS装饰器的用法

装饰器是NestJS框架中极具特色的功能,但很多开发者仅仅停留在"知道"层面,遇到实际项目仍然无从下手。本文将带你跳出枯燥的语法定义,通过5个真实项目场景,掌握装饰器的实战应用技巧。

1. 用装饰器实现API请求日志记录

在线上项目中,我们经常需要记录每个API的请求信息用于监控和调试。传统做法是在每个控制器方法中手动添加日志代码,这不仅重复劳动,还会污染业务逻辑。来看看如何用装饰器优雅解决:

// 定义日志装饰器 function LogRequest() { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = async function(...args: any[]) { const request = args[0]; // Express的request对象 console.log(`[${new Date().toISOString()}] ${request.method} ${request.url}`); return originalMethod.apply(this, args); }; }; } // 在控制器中使用 @Controller('users') export class UsersController { @Get() @LogRequest() // 只需添加这个装饰器 async findAll() { // 纯净的业务逻辑 return userService.findAll(); } }

这个案例展示了方法装饰器的典型应用场景。通过将横切关注点(日志记录)与业务逻辑分离,代码变得更加清晰可维护。

2. 属性装饰器自动验证DTO字段

表单验证是Web开发中的常见需求。传统做法是在业务代码中手动检查每个字段,不仅繁琐而且容易遗漏。下面这个例子演示如何用属性装饰器自动验证DTO:

// 定义验证装饰器 function ValidateEmail() { return function(target: any, propertyKey: string) { let value: string; const getter = () => value; const setter = (newVal: string) => { if (!newVal.includes('@')) { throw new Error('Invalid email format'); } value = newVal; }; Object.defineProperty(target, propertyKey, { get: getter, set: setter, enumerable: true, configurable: true }); }; } // 在DTO中使用 export class CreateUserDto { @ValidateEmail() email: string; // 其他字段... } // 控制器中自动验证 @Post() create(@Body() createUserDto: CreateUserDto) { // 如果email格式错误,上面已经自动抛出异常 return userService.create(createUserDto); }

提示:NestJS内置了class-validator库,实际项目中可以直接使用@IsEmail()等现成装饰器。这里展示的是其底层实现原理。

3. 方法装饰器实现权限控制

权限系统是后台管理项目的标配。下面我们实现一个简单的角色检查装饰器:

// 角色检查装饰器 function Roles(...roles: string[]) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = function(...args: any[]) { const request = args[0]; const userRole = request.user?.role; // 假设用户信息已注入请求 if (!roles.includes(userRole)) { throw new ForbiddenException('Insufficient permissions'); } return originalMethod.apply(this, args); }; }; } // 使用示例 @Controller('admin') export class AdminController { @Get('dashboard') @Roles('admin', 'superadmin') // 只允许admin和superadmin访问 getDashboard() { return adminService.getDashboardData(); } }

这个装饰器可以灵活地应用到任何需要权限控制的方法上,而且权限规则一目了然。

4. 参数装饰器便捷获取用户信息

在认证过的请求中,我们经常需要获取当前用户信息。传统方式是从request对象中手动提取,而参数装饰器可以让这个过程更加优雅:

// 定义用户信息装饰器 function CurrentUser() { return createParamDecorator((data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; // 假设认证中间件已注入user }); } // 使用示例 @Controller('profile') export class ProfileController { @Get() getProfile(@CurrentUser() user: User) { // 直接注入用户对象 return profileService.getProfile(user.id); } }

NestJS内置了@Req()、@Res()等参数装饰器,理解了这个原理,你就能创建自己的参数装饰器来简化开发。

5. 组合装饰器实现自定义缓存逻辑

最后一个案例展示如何组合多个装饰器实现复杂功能。我们将创建一个缓存装饰器,可以指定缓存时间和键前缀:

// 缓存装饰器工厂 function Cache(ttl: number, keyPrefix?: string) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; const cache = new Map(); // 实际项目应该用Redis等 descriptor.value = async function(...args: any[]) { const cacheKey = keyPrefix ? `${keyPrefix}_${JSON.stringify(args)}` : `${propertyKey}_${JSON.stringify(args)}`; if (cache.has(cacheKey)) { return cache.get(cacheKey); } const result = await originalMethod.apply(this, args); cache.set(cacheKey, result); // 设置过期时间 setTimeout(() => cache.delete(cacheKey), ttl * 1000); return result; }; }; } // 使用示例 @Controller('products') export class ProductsController { @Get() @Cache(60, 'products_list') // 缓存60秒 async findAll(@Query() query: PaginationQuery) { return productService.findAll(query); } }

这个案例展示了装饰器的强大组合能力。通过参数化配置,我们可以创建高度可复用的功能模块。

装饰器使用的最佳实践

在项目中使用装饰器时,有几个关键点需要注意:

  1. 保持单一职责:每个装饰器应该只做一件事,复杂逻辑可以通过组合多个装饰器实现
  2. 注意执行顺序:方法装饰器从下往上执行,类装饰器从内往外执行
  3. 避免过度使用:装饰器虽然强大,但过度使用会让代码变得难以理解
  4. 考虑性能影响:装饰器会在运行时修改目标,可能带来轻微性能开销

装饰器是NestJS框架的核心特性之一,掌握它的实战应用能显著提升代码质量和开发效率。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/13 10:26:44

基于TypeScript的Polymarket预测市场自动化交易机器人开发指南

1. 项目概述:一个用于Polymarket预测市场的五分钟交易机器人骨架 如果你对加密货币、体育赛事或者政治事件的预测市场感兴趣,并且想尝试用代码来自动化交易决策,那么你很可能听说过Polymarket。这是一个基于区块链的预测市场平台,…

作者头像 李华
网站建设 2026/5/13 10:21:08

Paperless-ngx开发环境极速配置:从零到调试的全链路实践

Paperless-ngx开发环境极速配置:从零到调试的全链路实践 【免费下载链接】paperless-ngx A community-supported supercharged document management system: scan, index and archive all your documents 项目地址: https://gitcode.com/GitHub_Trending/pa/paper…

作者头像 李华
网站建设 2026/5/13 10:19:08

3步解锁中文版Figma:FigmaCN让全球设计工具说你的语言

3步解锁中文版Figma:FigmaCN让全球设计工具说你的语言 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 你是否曾经因为Figma的英文界面而犹豫不决?作为全球最受欢…

作者头像 李华
网站建设 2026/5/13 10:18:37

while和for循环应用

while和for循环应用 while 循环和 until 循环的应用实践 当型和直到型循环语法 while 循环语句 while <条件表达式> do指令... done当型和直到型循环的基本范例 竖向打印54321 while格式&#xff1a; #!/bin/bash i5 while ((i>0)) doecho $i((i--)) done计算123…991…

作者头像 李华