Controller - 控制路由的指路人

關於 Controller

首先第一位登場的是 Controller,它在 NestJS 中的定位就是指路人的角色,會將跑進來的請求導引到對應的服務去,在整個請求到回應的過程裡是屬於比較前面的階段,也掌管著路由的分配。

建立 Controller

除了手動建立對應的 controller 檔案外,也可以透過 CLI 指令來快速生成對應的檔案:

$ nest g controller <name> # g 為 generate 的縮寫

Nest 除了會自動建立資料夾並新增 controller 和其它測試檔案,同時也會在根目錄的 module 中自動將其導入進去

路由對應

在 controller 當中是使用 class 和 decorator 來形成一組控制器,並掌管該組的路由對應,並搭配不同的方法 ( method ) 來處理不同類型的請求,例如:

import { Controller, Get } from '@nestjs/common';

@Controller('computers')
export class ComputersController {
  @Get()
  findAll(): string {
    return 'This action returns all computers';
  }
}

其中 @Controller() 裝飾器即是為底下的 class 宣告為 controller,並且在括號內帶入的值會成為這組控制器的根路由,而在 class 裡面的方法則是定義底下的子路由所對應的回傳,例如 findAll() 套上了 @Get() 裝飾器便形成了一個 GET 方法,可以透過 /computers 來取得回傳的內容,至於括號內的參數可以指定子路由,例如 @Get("list") 就會對應到 /computers/list 。下面也有常用到的裝飾器可以用來做宣告:

  • @Get():宣告一個 GET method

  • @Post():宣告一個 POST method

  • @Put():宣告一個 PUT method

  • @Delete():宣告一個 DELETE method

  • @All():宣告一個對應所有類型的 method

  • @Header():宣告方法的標頭屬性

  • @Redirect():重新導向到新的網址

路由參數

想要匹配到路由的參數,可以使用 : 作為開頭來指定參數名稱。

@Get(':id')
findOne(@Param() params: { id: string }): string {
  return 'This action returns a computer';
}

查詢參數

若是請求的方法中帶有查詢參數,可以在函式中引用 @Query() 來捕獲對應的查詢參數名稱。

@Get()
findByQuery(@Query() query: { version: string }): string {
  return `This action returns a computer with version ${version}`;
}

通配路由

另外,在路由的對應方面,也適用ㄧ部分的 正規表達式 來讓單一方法兼容不同的路由:

例如 @Get("compu*ters") 可以對應到 /computers 或是 /compuuuuuuters 等。

Body 資料

ㄧ般在建構 POST 的方法時,會希望發送請求者帶上 body 資料來讓後端接收並根據傳來的參數來進行處理,那麼當請求到 Controller 時我們就可以透過 @Body() 來將這些帶進來的參數進行讀取並利用。

@Controller('computers')
export class ComputersController {
  @Post()
  create(@Body() data: { title: string; description?: string }) {
    return {
      message: 'This action adds a new computer',
      data,
    };
  }
}

也可以拆開來寫成:

@Controller('computers')
export class ComputersController {
  @Post()
  create(
    @Body('title') title: string,
    @Body('description') description?: string,
  ) {
    return {
      message: 'This action adds a new computer',
      title,
      description,
    };
  }

DTO

不過ㄧ般的情況下,會使用 DTO 來讓參數的格式較為統一並集中管理,也可以讓 Controller 內減少ㄧ些較為繁雜的型別宣告,提高可維護性。DTO 是 Data Transfer Object 的縮寫,是一個唯讀屬性的物件類型,在 Nest 裡習慣上會根據 Controller 的名稱在該目錄底下建立對應的 .dto.ts 檔案,至於類別的撰寫則是推薦使用原生的 JS class 而非 TS 的 interface,因為前者在程式被編譯後仍然會被保留下來而後者不會。

// create-computers.dto.ts
export class CreateComputersDto {
  public readonly title: string;
  public readonly description?: string;
}

// computers.controller.ts
@Controller('computers')
export class ComputersController {
  @Post()
  create(@Body() dto: CreateComputersDto) {
    return {
      message: 'This action adds a new computer',
      title: dto.title,
      description: dto.description,
    };
  }
}

Copyright© 2026 ZeoXer. All Rights Reserved.