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, }; } }