流程图javaandroidnestJS

NestJS 装饰器:类装饰器和方法装饰器怎么分

用控制器和服务的常见例子解释 NestJS 类装饰器、方法装饰器、参数装饰器分别作用在哪一层,并说明它们在一次请求里的执行位置。

·更新于 ·阅读约 6 分钟·计算中...
NestJS 装饰器:类装饰器和方法装饰器怎么分

NestJS 里的装饰器很多,但新手最容易混的是:@Controller()@Injectable() 这种“贴在类上”的,和 @Get()@Post() 这种“贴在方法上”的,到底差在哪。最短的理解方式是:

  • 类装饰器决定“这个类是什么”
  • 方法装饰器决定“这个方法怎么被框架使用”

在这里插入图片描述

目录

先看三个层级

在 NestJS 里,常见装饰器大致可以分成:

  • 类装饰器
  • 方法装饰器
  • 参数装饰器

这三个层级刚好对应“控制器是谁”“具体路由怎么进”“请求数据怎么取”。

类装饰器做什么

类装饰器贴在整个类上,用来告诉 Nest 这个类的角色。

import { Controller, Injectable } from "@nestjs/common"

@Controller("users")
export class UserController {}

@Injectable()
export class UserService {}

这类装饰器常见作用:

  • 标记控制器
  • 标记 provider / service
  • 标记模块

Nest 官方控制器文档本身也是围绕 @Controller() 展开的:它负责把类和路由前缀关联起来。

方法装饰器做什么

方法装饰器贴在类的方法上,用来说明“这个方法对应什么行为”。

import { Controller, Get, Post } from "@nestjs/common"

@Controller("users")
export class UserController {
  @Get()
  findAll() {
    return "all users"
  }

  @Post()
  create() {
    return "created"
  }
}

最常见的是:

  • @Get()
  • @Post()
  • @Put()
  • @Delete()
  • @UseGuards()
  • @UseInterceptors()

也就是说,类装饰器先告诉框架“这是哪栋楼”,方法装饰器再告诉框架“楼里的哪扇门处理什么请求”。

参数装饰器别混进方法装饰器里

很多人把 @Body()@Param()@Query() 也跟 @Get() 放一类,其实它们更接近“方法参数级别”的装饰器:

@Get(":id")
findOne(@Param("id") id: string) {
  return id
}

它们解决的是“请求数据如何注入到这个参数”,而不是“这个方法绑定哪个路由”。

一次请求里它们分别在哪一层生效

可以把一条请求大致理解成:

请求进入
-> 通过 @Controller() 找到控制器前缀
-> 通过 @Get() / @Post() 找到具体方法
-> 通过 @Param() / @Body() 取数据
-> 调用 controller 方法
-> controller 调 service(通常由 @Injectable() 标记)

这就解释了为什么 @Injectable()@Get() 根本不是同类东西。一个是在注册可注入类,一个是在声明路由处理器。

最容易混淆的几个点

@Controller()@Get() 不是替代关系

它们通常一起出现,但解决的问题不同:

  • @Controller("users") 提供类级路由前缀
  • @Get() 提供方法级 HTTP 映射

最终才得到完整路径。

@Injectable() 不会自动让方法变成路由

它只告诉 Nest 这个类可以参与依赖注入,常见于 service、repository、use case 层。

@UseGuards() 既能挂类,也能挂方法

这类装饰器容易让人困惑,因为它既可以类级应用,也可以方法级覆盖。判断方式很简单:看你是想整类共享,还是只限某个接口。

记忆法

  • 类装饰器:这是什么角色
  • 方法装饰器:这个方法处理什么请求或行为
  • 参数装饰器:这个参数从哪里来

结论

  • @Controller()@Injectable() 这类是类装饰器,作用在整个类。
  • @Get()@Post() 这类是方法装饰器,作用在具体方法。
  • @Body()@Param() 这类是参数装饰器,负责把请求数据注入参数。

如果你接下来在写 DTO 校验、管道或响应拦截,最好把它们按“请求链路位置”继续拆开理解,而不是统称“装饰器语法”。

参考资料

继续阅读

订阅 FreeMac

每周精选:免费 Mac 软件评测、可信来源更新、替代方案和少折腾指南。