文章目录
控制器 (Controller)
控制器负责处理传入请求并向客户端返回响应。
控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器都有不止一条路由,不同的路由可以执行不同的操作。
为了创建基本控制器,我们会使用到类和装饰器。装饰器将类与所需的元数据相关联,并使 Nest 能够创建路由映射(将请求绑定到相应的控制器)。
*路由 (router)
接下来我们会使用@Controller()
装饰器,这是定义基本控制器所必需的。在@Controller()
装饰器中使用路径前缀可以让我们轻松地对一组相关路由进行分组,并最大限度地减少重复代码。
我们可以将一组路由分组,它们的管理与路由/dogs
下的狗实体交互。这样的话,就不必为文件中的每个路由重复该部分路径。
首先在src
目录下创建一个名为dogs
的文件夹;随后在dogs
文件夹内创建一个名为dogs.controller.ts
文件:
注意: 你也可以不需要遵循如此严格的目录格式。你可以在 命令行 中输入 nest g controller [name]
命令来通过CLI 创建对应的控制器 (此处的name 为dogs ) 。随后找到你的dogs.controller.ts
文件:
/* dogs.controller.ts */
import { Controller, Get } from '@nestjs/common';
@Controller('dogs')
export class DogsController {
@Get()
findAll(): string {
return 'This action will return all dogs!';
}
}
为了保证代码的阅读性,就不在代码内添加注释了,在下面为读者逐一讲解:
-
@Controller('dogs')
:小括号内的'dogs'
便是我们的路由, 即/dogs
; -
@Get()
:此装饰器对应的就是我们HTTP 对应的请求方法,你同样可以在内部声明一个前缀,比如@Get('name')
,这样的组合会为像GET /dogs/name
这样的请求生成路由映射; -
findAll()
:这个方法名称是我们自己定义的,声明的名称足够语义化就可以。
请求对象 (request object)
处理程序通常需要访问客户端请求的详细信息。我们可以通过将@Req()
装饰器添加到处理程序的签名来指示Nest 注入它来访问请求对象。
此处会在我们上面的代码基础之上,添加一些内容来达成访问客户端请求的详细信息的功能。
/* dogs.controller.ts */
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller('dogs')
export class DogsController {
@Get()
findAll(@Req() request: Request): string {
return 'This action will return all dogs!';
}
}
注意上方添加的点:
-
首先是
import
的导入内容变多了,此内容一般不需要我们手动添加,当你使用时会自动添加; -
@Req()
装饰器是写在了findAll( ) 方法的参数内部的。
*资源 (Resources)
这里直白的说,GET 路由就是用来获取 dogs资源的,专业一点叫定义了一个端点;那通常还会提供一个创建新记录的端点。所以接下来我们来创建POST 处理程序:
仍然在dogs.controller.ts
文件中,但是注意,下方的代码并没有做上方的添加@Req()
装饰器的功能,而是基于第一段代码:
/* dogs.controller.ts */
import { Controller, Get, Post } from '@nestjs/common';
@Controller('dogs')
export class DogsController {
@Post()
create(): string {
return `This action will add a new dog.`;
}
@Get()
findAll(): string {
return `This action will return all dogs!`;
}
}
所以这一步其实不难对么?Nest 为所有标准的HTTP 方法提供了装饰器:@Get()
、@Post()
、@Put()
、@Delete()
、@Patch()
、@Options()
和 @Head()
。此外,@All()
定义了一个端点来处理所有的HTTP 方法。
状态码 (status code)
默认情况下,响应状态代码为200 (除了POST 请求的代码为 201) 。通过在处理程序级别添加@HttpCode(...)
装饰器来轻松更改此行为。
简单的例子:
import { HttpCode } from '@nestjs/common';
@Post()
@HttpCode(204)
create(): string {
return `This action will add a new dog`;
}
标头 & 重定向 (headers & redirection)
要指定自定义响应标头,可以通过Header()
装饰器;要将响应重定向到特定的URL ,可以使用@Redirect()
装饰器:
其中@Redirect()
有两个参数,为url
和statusCode
,均为可选。如果省略的话则statusCode
的默认值为302
。
下方是两个简单的例子:
/* 标头 */
@Post()
@Header('Cache-Control', 'none')
create() {
return `This action will add a new dog.`;
}
/* 重定向 */
@Get()
@Redirect('URL', 301)
*路由参数 (route parameters)
当你需要接受动态数据作为请求的一部分时 (例如,GET /dogs/1
获取ID 为1 的dog) ,具有静态路径的路由将不起作用。为了定义带参数的路由,我们可以在路由的路径中添加路由参数标记,以捕获请求 URL 中该位置的动态值。此时可以使用@Param()
装饰器。
下面的代码我们会对上面书写的@Get()
部分代码进行一下修改:
@Get(':id')
findOne(@Param() params: any): string {
console.log(params.id);
return `This action will return a #${param.id} dog.`;
}
@Param()
用于修饰方法参数,并使路由参数可用作方法体内该修饰方法参数的属性。例如像上方的代码,通过引用params.id
来访问id
参数。
当然也可以像下面的方法来传入一个特定的参数token
给装饰器,然后在方法体中直接通过名称引用路由参数:
@Get(':id')
findOne(@Param('id') id: string): string {
return `This action will return a #${id} dog.`;
}
*请求负载 (request payloads)
上方我们的 POST 路由处理程序不接受任何客户端参数。在这里我们会通过添加@Body()
装饰器来解决此问题。
在这里先科普一句DTO (数据传输对象) 架构。DTO 是定义数据如何通过网络发送的对象。
接下来让我们创建CreateDogDto
类,注意,此处为一个新的文件,同样创建在dogs
目录下,文件名为create-dog.dto.ts
:
/* create-dog.dto.ts */
export class CreateDogDto {
name: string;
age: number;
bark: string;
}
当我们创建完成后,就可以在DogsController
中使用新创建的DTO 了:
/* dogs.controller.ts */
// ...
@Post()
async create(@Body() createDogDto: CreateDogDto) {
return `This action will add a new dog.`;
}
// ...
在这里说一句人话,其实 请求负载 它还有一个名字就是我们的 请求体 ,发送POST 请求时所携带的参数均会放在这个请求体中。
接下来让我们来补全剩下的两个常用HTTP请求吧 ( PUT & DELETE ):
/* dogs.controller.ts */
/* 本代码块 会展示该文件目前 所有的代码 */
import { Body, Controller, Delete, Get, Param, Post, Put } from "@nestjs/common";
import { CreateDogDto } from "./dto/create-dog.dto";
import { UpdateDogDto } from "./dto/update-dog.dto";
@Controller('dogs')
export class DogsController {
@Post()
async create(@Body() createDogDto: CreateDogDto) {
return `This action will create a new dog!`;
}
@Get()
findAll(): string {
return `This action will return all dogs!`;
}
@Get(':id')
findOne(@Param() params: any): string {
return `This action will return a #${params.id} dog!`;
}
@Put(':id')
update(@Param('id') id: string, @Body() updateDogDto: UpdateDogDto): string {
return `This action will update #${id} dog.`;
}
@Delete(':id')
remove(@Param('id') id: string): string {
return `This action will remove #${id} dog.`;
}
}
此时可以看一下我们src
目录下的结构:
启动并运行
虽然我们已经完全定义了上述的控制器 (Controller ),但是 Nest 不知道DogsController
的存在,所以不会创建此类的实例。
这是因为:控制器始终属于一个模块,这也是我们在@Module()
装饰器中包含controllers
数组的原因。因为还没有定义除根AppMoudule
之外的任何其他模块。所以接下来的操作是引入:
/* app.module.ts */
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DogsController } from './dogs/dogs.controller';
@Module({
imports: [],
// 在controllers 数组内部添加我们的控制器 DogsController
controllers: [AppController, DogsController],
providers: [AppService],
})
export class AppModule {}
通过使用 @Module()
装饰器 将元数据附加到模块类,Nest 现在可以轻松反映必须安装哪些控制器。
现在你便可以在浏览器内测试你的GET 请求了。
如下图:
附带id
的GET 请求结果:
为什么我要说测试GET 请求?其他的不行吗?
不行。
所以这里大家可以下载一个ApiFox,在其内部可以轻松创建快捷请求。在这里便给大家截几张图示范一下:
POST 请求:
PUT 请求:
DELETE 请求:
小结
以上便是控制器一些最基本的概念和知识了。上文的代码也均已经测试过,可以跑通。通过最简单的例子来逐步学习知识也是一个非常好的方法。如果有不同见解和其他想法,很欢迎来交流和沟通!
标签:控制器,return,请求,dogs,Controller,NestJS,id,路由,string From: https://blog.csdn.net/LZwarning0215/article/details/142555364