【NestJS系列】核心概念:Controller控制器

前言

控制器主要是用來處理客戶端傳入的請求並向客戶端返回響應。

它一般是用來做路由導航的,內部路由機制控制哪個控制器接收哪些請求。

路由

爲了創建基本控制器,我們需要使用@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 基本類型(例如,stringnumberboolean)時,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'路徑將匹配abcdab_cdabecd等。字符?+*()可以在路由路徑中使用,並且是其正則表達式對應項的子集。連字符 ( -) 和點 ( .) 按字面意思解釋爲基於字符串的路徑。

請求對象

作爲後端項目,訪問客戶端請求的詳細信息也非常重要,從上面生成的代碼中我們可以看到@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.queryQuery獲取的是一致的,所以使用@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 爲 1nanjiu)時,具有靜態路徑的路由將不起作用。爲了定義帶參數的路由,我們可以在路由的路徑中添加路由參數**標記,以捕獲請求 URL 中該位置的動態值。**下面裝飾器示例中的路由參數標記@Get()演示了這種用法。以這種方式聲明的路由參數可以使用裝飾器來訪問@Param()

// nanjiu.controller.ts
@Get(':id')
  findOne(@Param() params) {
    console.log('params', params)
    return this.nanjiuService.findOne(+params.id);
  }

查看日誌

狀態碼

從上面幾個例子我們可以看到,默認情況下響應狀態碼都是200POST請求除外,POST默認爲201Nest同樣提供了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);
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章