NestJS 常用装饰器
装饰器是什么?
简单来说,装饰器就是一个函数,它可以附加到类、方法、属性或参数上,给它们添加一些额外的信息或行为。Nest 内部会读取这些信息,然后做相应的处理。比如你在类上贴了 @Controller('user'),Nest 就知道这个类是用来处理 /user 路径的请求的。
Nest 的装饰器主要分几大类:模块相关、控制器相关、路由方法相关、参数相关、异常处理相关,还有元数据相关。下面我们挨个来看。
一、模块定义装饰器
这些装饰器用来定义和组织模块,以及声明依赖。
@Module()
这是最基础的装饰器,用来声明一个 Nest 模块。它接收一个对象,包含 imports、controllers、providers、exports 等属性。模块是组织代码的基本单位。
@Module({
imports: [OtherModule],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}@Global()
如果你希望一个模块被全局共享,也就是它的 providers 可以在任何地方注入,不需要在别的模块里 imports,就可以加上 @Global()。
@Global()
@Module({
providers: [ConfigService],
exports: [ConfigService],
})
export class ConfigModule {}注意:全局模块尽量少用,否则会让依赖关系变得不清晰。
@Injectable()
这个装饰器标记一个类可以被 Nest 的 IoC 容器管理,也就是可以被注入到其他地方。通常用于 Service、Repository、Helper 等。
@Injectable()
export class UserService {
// ...
}@Inject()
通常情况下,Nest 会根据类型自动注入依赖。但有时候 token 可能不是 class(比如是一个字符串或 Symbol),这时候就需要用 @Inject() 手动指定 token。
@Injectable()
export class UserService {
constructor(@Inject('CONFIG') private config: any) {}
}@Optional()
如果注入的依赖是可选的,也就是说可能不存在,加上 @Optional() 可以避免报错。如果没有找到对应的 provider,就注入 undefined。
@Injectable()
export class UserService {
constructor(@Optional() private logger?: LoggerService) {}
}二、控制器与路由方法装饰器
这些装饰器用来定义控制器和路由。
@Controller()
标记一个类为控制器,可以指定路由前缀。
@Controller('users')
export class UserController {
// 所有路由都会带上 /users 前缀
}HTTP 方法装饰器:@Get()、@Post()、@Put()、@Delete()、@Patch()、@Options()、@Head()
这些装饰器用在控制器的方法上,表示该方法处理对应 HTTP 方法的请求。可以传入路径,也可以不传(默认就是控制器路径)。
@Get(':id')
findOne(@Param('id') id: string) {
return `user ${id}`;
}
@Post()
create(@Body() createUserDto: CreateUserDto) {
// ...
}@HttpCode()
默认情况下,POST 成功返回 201,GET 成功返回 200。如果你想修改状态码,可以用 @HttpCode()。
@Post()
@HttpCode(204)
create() {
// 返回 204 No Content
}@Header()
如果你想自定义响应头,可以用 @Header()。
@Get()
@Header('Cache-Control', 'no-cache')
findAll() {
// ...
}@Redirect()
如果你需要重定向,可以用 @Redirect() 指定要跳转的 URL 和状态码(默认 302)。
@Get('docs')
@Redirect('https://docs.nestjs.com', 301)
getDocs() {
// 也可以动态返回重定向信息
}@Render()
如果你在用模板引擎(比如 Handlebars),可以用 @Render() 指定渲染的模板文件名。
@Get('profile')
@Render('profile.hbs')
getProfile() {
return { name: 'John' }; // 传递给模板的数据
}三、参数装饰器
这些装饰器用在控制器方法的参数上,用来从请求中提取数据。
@Param()
用于获取路由参数,比如 /users/:id 中的 id。
@Get(':id')
findOne(@Param('id') id: string) {
return `user ${id}`;
}如果不传参数名,会拿到整个 params 对象:@Param() params。
@Query()
用于获取 query string 参数,比如 /users?name=john 中的 name。
@Get()
findAll(@Query('name') name: string) {
// ...
}@Body()
用于获取请求体(request body),通常配合 DTO 类使用。
@Post()
create(@Body() createUserDto: CreateUserDto) {
// ...
}@Headers()
用于获取请求头。可以指定某个头,也可以获取全部。
@Get()
getHeaders(@Headers('user-agent') userAgent: string) {
// ...
}@Session()
如果你使用了 express-session 中间件,可以用 @Session() 获取 session 对象。
@Get()
getSession(@Session() session: any) {
// ...
}@HostParam()
用于获取 host 里的参数,比如在域名里定义变量(@Controller(':tenant.example.com'))时,可以用它取到 tenant。
@Controller(':tenant.example.com')
getTenant(@HostParam('tenant') tenant: string) {
// ...
}@Req() / @Request()
注入原始的请求对象(Express 的 Request)。用了这个装饰器,Nest 就不会自动解析参数了,你需要自己从 request 里取数据。
@Get()
getRequest(@Req() req: Request) {
console.log(req.url);
}@Res() / @Response()
注入原始的响应对象。一旦用了 @Res(),Nest 就不会自动帮你发送响应了,你需要手动调用 res.send() 等方法。如果你只是想要设置某些响应头,还可以继续让 Nest 处理响应,可以传入 { passthrough: true }。
@Get()
getResponse(@Res({ passthrough: true }) res: Response) {
res.setHeader('X-Custom', 'hello');
return 'ok'; // 仍然由 Nest 发送
}@Next()
注入 next 函数,通常用于中间件中,表示下一个处理函数。
@Get()
handle(@Next() next: () => void) {
// ...
}四、异常处理与拦截相关装饰器
@Catch()
用于声明一个异常过滤器要捕获哪些异常。放在异常过滤器类上。
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
// ...
}
}@UseFilters()
在控制器或方法上应用异常过滤器。
@UseFilters(HttpExceptionFilter)
@Controller('users')
export class UserController {}@UsePipes()
在控制器或方法上应用管道。
@UsePipes(ValidationPipe)
@Post()
create(@Body() dto: CreateUserDto) {}@UseInterceptors()
在控制器或方法上应用拦截器。
@UseInterceptors(LoggingInterceptor)
@Get()
findAll() {}@UseGuards()
虽然不在列表里,但也是常用装饰器,用于应用守卫。列表里没写,我们可以提一下。
@UseGuards(AuthGuard)
@Get('profile')
getProfile() {}五、元数据装饰器
@SetMetadata()
用来给类或方法附加自定义元数据,然后可以在守卫、拦截器里通过 Reflector 读取。这是实现自定义装饰器的底层工具。
@SetMetadata('roles', ['admin'])
@Get()
findAll() {}通常你不会直接用 @SetMetadata,而是封装成自定义装饰器。
总结一下
掌握了这些装饰器,你就能写出结构清晰、易于维护的代码。上面列出来的都是最常用的,实际开发中还会遇到一些场景组合,比如自定义装饰器来简化重复逻辑。

Comments | NOTHING