在 Nest 的世界里,Controller 负责路由的配置并处理来自客户端的请求,而每一个 Controller 都可以依照需求来设计不同 Http Method 的资源,就好像外场服务生负责带位、协助客人点餐一样,并根据客户的需求做出相对应的回应:
总体来说,Controller 就是一个处理客户端请求,并将相同性质的资源整合在一起的元件。
所有的 Controller 都必须使用 @Controller
装饰器来定义。可以用 NestCLI 快速生成 Controller:
$ nest generate controller <CONTROLLER_NAME>
注意:
<CONTROLLER_NAME>
可以含有路径,如:features/todo
,这样就会在src
资料夹下建立该路径并含有 Controller。
这边我建立了一个名为 todo
的 Controller:
$ nest generate controller todo
在 src
底下会看见一个名为 todo
的资料夹,里面有 todo.controller.ts
以及 todo.controller.spec.ts
:
由於只有建立 Controller,所以会自动将其归纳於根模组下,也就是说 AppModule
会多引入 TodoController
:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TodoController } from './todo/todo.controller';
@Module({
imports: [],
controllers: [AppController, TodoController],
providers: [AppService],
})
export class AppModule {}
在建置完 Controller 基本骨架後,会发现 todo.controller.ts
的 @Controller
多了一个字串 todo
,这是路由的 前缀 (prefix):
import { Controller } from '@nestjs/common';
@Controller('todo')
export class TodoController {}
注意:透过 NestCLI 建立的 Controller 前缀预设使用该 Controller 的名称,通常会习惯把名称取单数,而前缀改为复数。
添加路由前缀的好处是可以使相同路由的资源都归纳在同一个 Controller 里面,其中包含了前缀底下的所有子路由:
可以透过添加装饰器在 class
的方法上,来指定不同 Http Method 所呼叫的方法,Nest 会根据 Controller 与指定的 Http Method 装饰器来建立路由表。以下方程序码为例,使用的为 GET
:
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
getAll() {
return [];
}
}
使用浏览器进入 http://localhost:3000/todos 来查看结果:
Nest 的 Http Method 装饰器名称即对应标准 Http Method,这里做了些归纳:
@Get
:表示接收对应路由且为 GET
请求时触发。@Post
:表示接收对应路由且为 POST
请求时触发。@Put
:表示接收对应路由且为 PUT
请求时触发。@Patch
:表示接收对应路由且为 PATCH
请求时触发。@Delete
:表示接收对应路由且为 DELETE
请求时触发。@Options
:表示接收对应路由且为 OPTIONS
请求时触发。@Head
:表示接收对应路由且为 HEAD
请求时触发。@All
:表示接收对应路由且为以上任何方式的请求时触发。在设计路由时,很有可能会有子路由的需求,比如说:/todos
底下还有一个取得范例的资源,定义为 GET /todos/examples
,但不可能每次有子路由都建立一个新的 Controller,这时候就可以透过 Http Method 装饰器指定子路由,会基於 Controller 设置的前缀来建立,以下方程序码为例,取得资源的路由为 GET /todos/examples
:
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get('/examples')
getExample() {
return [
{
id: 1,
title: 'Example 1',
description: ''
}
];
}
}
使用浏览器进入 http://localhost:3000/todos/examples 查看结果:
注意:该用法使用上需要谨慎,基本上除了
?
以外,都是被允许的字元。
有时候设计路由时,可能会提供些许的容错空间,比如说:原本是 GET /todos/examples
,但不管是 /todos/exammmmmmmmples
还是 /todos/exam_ples
都可以得到 /todos/examples
的结果,主要是在指定路由时,使用了 *
。下方为范例程序码:
import { Controller, Get } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get('exam*ples')
get() {
return [
{
id: 1,
title: 'Example 1',
description: ''
}
];
}
}
使用浏览器进入 http://localhost:3000/todos/exammmmmmmmples 查看结果:
路由参数的设计十分简单,会在 Http Method 装饰器上做定义,字串格式为 :<PARAMETER_NAME>
,接着要在该方法中添加带有 @Param
装饰器的参数,这样就可以顺利取得路由参数。这里我们新增一个路由参数为 id
的路由,程序码如下:
import { Controller, Get, Param } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get(':id')
get(@Param() params: { id: string }) {
const { id } = params;
return {
id,
title: `Title ${id}`,
description: ''
};
}
}
这里还有另一种方式可以取得特定路由参数,就是在 @Param
带入指定参数名称:
import { Controller, Get, Param } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get(':id')
get(@Param('id') id: string) {
return {
id,
title: `Title ${id}`,
description: ''
};
}
}
使用浏览器进入 http://localhost:3000/todos/1 查看结果:
查询参数与路由参数取得的方式很相似,但不需要在 Http Method 装饰器中做任何设置,只需要在方法中添加带有 @Query
的参数即可。这里我们做一个简单的范例:
import { Controller, Get, Query } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
getList(@Query() query: { limit: number, skip: number }) {
const { limit = 30, skip = 0 } = query;
const list = [
{
id: 1,
title: 'Title 1',
description: ''
},
{
id: 2,
title: 'Title 2',
description: ''
}
];
return list.slice(skip, limit);
}
}
也可以取得特定查询参数,就是在 @Query
带入指定参数名称:
import { Controller, Get, Query } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Get()
getList(
@Query('limit') limit: number = 30,
@Query('skip') skip: number = 0
) {
const list = [
{
id: 1,
title: 'Title 1',
description: ''
},
{
id: 2,
title: 'Title 2',
description: ''
}
];
return list.slice(skip, limit);
}
}
使用浏览器进入 http://localhost:3000/todos?limit=1 查看结果:
预设情况下,除了 POST 会回传 201
外,大多数的 Http Method 都是回传 200
,不过应该要以实际情况来回传适当的状态码。Nest 提供了状态码的 enum
,并用装饰器来设置回传的状态码,十分贴心!下方为范例程序码:
import { Controller, Patch, HttpCode, HttpStatus } from '@nestjs/common';
@Controller('todos')
export class TodoController {
@Patch()
@HttpCode(HttpStatus.NO_CONTENT)
get() {
return [];
}
}
这里用 Postman 来查看结果:
今天的内容稍微多了些,这边帮大家懒人包一下:
@Param
取得路由参数、透过 @Query
取得查询参数。@HttpCode
与 HttpStatus
来配置该资源回传的状态码。Controller 的功能非常多,如果都放在同一篇的话篇幅会过长,所以剩下的部分会在下一篇继续说明。
<<: # Day3--向左走?向右走?再走一次?那些替你做决定的小事
大家好,我是Crous,随着年纪增长,就业和出路的问题在脑里挥之不去,在今年夏天决定告别委靡不振的暑...
今天一样是实作,不过今天实作就比较稍微不一样,我们会先讲alert的用法,并且讲解如何在不同View...
前言 因为UI和UX方面的需求,这几天上网搜寻了如何自定义下一页的弹出大小,弹出位置和动画,发现有蛮...
工具介绍 今天要体验的工具是hydra,有别於先前体验过的其他工具,虽然也是透过字典档的形式,但它支...
客户:我的需求不多,就一点点... 设计师:(已预知接下来无穷尽的...浩瀚宇宙) 多人可同时协同设...