前言
控制器主要是用來處理客戶端傳入的請求並向客戶端返回響應。
它一般是用來做路由導航的,內部路由機制控制哪個控制器接收哪些請求。
路由
爲了創建基本控制器,我們需要使用@Controller
裝飾器,裝飾器將類與所需元數據關聯起來,並使Nest
能夠創建路由映射。
我們使用nest-cli
快速創建一個REST API風格的完整CURD代碼。
nest g resource nanjiu
在生成的nanjiu文件夾下,我們可以看到有nanjiu.controller.ts
文件,代碼如下:
// nanjiu.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common';
import { NanjiuService } from './nanjiu.service';
import { CreateNanjiuDto } from './dto/create-nanjiu.dto';
import { UpdateNanjiuDto } from './dto/update-nanjiu.dto';
@Controller('nanjiu')
export class NanjiuController {
constructor(private readonly nanjiuService: NanjiuService) {}
@Post()
create(@Body() createNanjiuDto: CreateNanjiuDto) {
return this.nanjiuService.create(createNanjiuDto);
}
@Get()
findAll(@Param() params, @Query() query) {
console.log('find', query)
return this.nanjiuService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.nanjiuService.findOne(+id);
}
@Patch(':id')
update(@Param('id') id: string, @Body() updateNanjiuDto: UpdateNanjiuDto) {
return this.nanjiuService.update(+id, updateNanjiuDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.nanjiuService.remove(+id);
}
}
@controller
裝飾器中傳入了nanjiu
參數,表示指定路由前綴nanjiu
,在@controller
裝飾器中使用路由前綴,可以讓我們很輕鬆地將一組相關路由放在一起集中管理。
比如當我們通過get
方式請求/nanjiu
這個路由時,它應該會走到@get
裝飾器修飾的findAll
方法內
可以使用ApiFox
工具進行接口測試:
從上圖中可以看到我此時的請求路徑是http://localhost:3000/apinanjiu
,是不是很好奇爲了什麼多了一層/api
,這是因爲我加了一層全局路由前綴
// main.ts
app.setGlobalPrefix('api'); // 全局路由前綴
這裏我們還可以看到狀態碼爲200,並且能夠看到findAll
的返回值,就說明此時的請求是正常的,但右邊還有個error提示返回數據結構與接口定義不一致。
這是因爲這裏我們只是簡單地返回了一個字符串,並不符合JSON格式
在Nest
中,有兩種選項來處理響應值:
-
標準模式:使用此內置方法,當請求處理程序返回 JavaScript 對象或數組時,它將自動序列化爲 JSON。然而,當它返回 JavaScript 基本類型(例如,
string
、number
、boolean
)時,Nest 將僅發送該值,而不嘗試對其進行序列化。這使得響應處理變得簡單:只需返回值,Nest 就會處理其餘的事情。此外,默認情況下,響應的狀態代碼始終爲 200,除了使用 201 的 POST 請求。我們可以通過
@HttpCode(...)
在處理程序級別添加裝飾器來輕鬆更改此行爲 -
特定庫模式:我們可以使用特定於庫的(例如,Express)響應對象
@Res()
,可以使用方法處理程序簽名中的裝飾器注入該對象(例如,findAll(@Res() response)
)。通過這種方法,您可以使用該對象公開的本機響應處理方法。例如,使用 Express,可以使用response.status(200).send()
.
路由通配符
Nest
還支持基於模式的路由,比如,使用通配符
@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}
路由'ab*cd'
路徑將匹配abcd
、ab_cd
、abecd
等。字符?
、+
、*
和()
可以在路由路徑中使用,並且是其正則表達式對應項的子集。連字符 ( -
) 和點 ( .
) 按字面意思解釋爲基於字符串的路徑。
請求對象
作爲後端項目,訪問客戶端請求的詳細信息也非常重要,從上面生成的代碼中我們可以看到@Body
、@Param
、@Query
等裝飾器,沒錯,在大多數時候我們並不需要手動獲取請求對象(查詢字符串、參數、請求頭、正文等),直接通過這些開箱即用的裝飾器就能快速獲取。
比如我們在findAll
內加上日誌
// nanjiu.controller.ts
@Get()
findAll(@Param() params, @Query() query) {
console.log('find', params, query) // 日誌
return this.nanjiuService.findAll();
}
然後在請求時帶上一些參數:
此時我們再來看看後端打印的日誌:
這裏就能看到前端請求傳過來的Query
參數爲city: shanghai
這些開箱即用的裝飾器有以下這些:
@Request(), @Req() |
req |
---|---|
@Response(), @Res() * |
res |
@Next() |
next |
@Session() |
req.session |
@Param(key?: string) |
req.params /req.params[key] |
@Body(key?: string) |
req.body /req.body[key] |
@Query(key?: string) |
req.query /req.query[key] |
@Headers(name?: string) |
req.headers /req.headers[name] |
@Ip() |
req.ip |
@HostParam() |
req.hosts |
HTTP請求方法
從上面生成的代碼中的,我們可以發現除了@Get
請求方法裝飾器外還有一些其它的,事實上,Nest
爲所有標準 HTTP 方法提供了裝飾器:@Get()
、@Post()
、@Put()
、@Delete()
、@Patch()
、@Options()
和@Head()
。
一般大家常用的都是get
請求與post
請求吧,好像很少看到其它類型的請求
獲取get請求參數
這裏可以使用@Request
裝飾器與@Query
裝飾器,與express
完全一致
上面已經演示了通過@Query
獲取,那就在通過@Request
再演示一遍
// nanjiu.controller.ts
@Get()
findAll(@Request() req, @Query() query) {
console.log('find', req.query, query)
return this.nanjiuService.findAll();
}
通過req.query
與Query
獲取的是一致的,所以使用@Query
裝飾器獲取get
類型的請求參數會更方便一些,如果你還想獲取更多關於請求的參數可以使用@Request
裝飾器。
獲取post請求參數
與express
一樣,可以使用@Request
裝飾器與Body
裝飾器
// nanjiu.controller.ts
@Post()
create(@Body() createNanjiuDto: CreateNanjiuDto) {
console.log('body', createNanjiuDto)
return this.nanjiuService.create(createNanjiuDto);
}
查看日誌
動態路由
當需要接受動態數據作爲請求的一部分(例如,GET /nanjiu/1
獲取帶有 id 爲 1
的nanjiu
)時,具有靜態路徑的路由將不起作用。爲了定義帶參數的路由,我們可以在路由的路徑中添加路由參數**標記,以捕獲請求 URL 中該位置的動態值。**下面裝飾器示例中的路由參數標記@Get()
演示了這種用法。以這種方式聲明的路由參數可以使用裝飾器來訪問@Param()
// nanjiu.controller.ts
@Get(':id')
findOne(@Param() params) {
console.log('params', params)
return this.nanjiuService.findOne(+params.id);
}
查看日誌
狀態碼
從上面幾個例子我們可以看到,默認情況下響應狀態碼都是200
,POST
請求除外,POST
默認爲201
,Nest
同樣提供了HttpCode()
裝飾器來自定義響應狀態碼
// nanjiu.controller.ts
@Get()
@HttpCode(202)
findAll(@Request() req, @Query() query) {
console.log('find', req, query)
return this.nanjiuService.findAll();
}
響應頭
想要自定義響應頭,可以使用@Header
裝飾器
@Post()
@Header('Cache-Control', 'none')
create(@Body() createNanjiuDto: CreateNanjiuDto) {
console.log('body', createNanjiuDto)
return this.nanjiuService.create(createNanjiuDto);
}