作者:markzzw 时间:2024-1-31
线上代码:CodeSandbox
Github:zhangzewei/nest-learning-tutorial
系列阅读
在NestJS应用程序开发中,DTO(Data Transfer Object)是一个重要的概念。DTO用于在不同的层之间传输数据,并且在实现松耦合和数据验证方面发挥了关键的作用。在本篇【NestJS学习日记】中,我们将深入探讨DTO的概念和在NestJS应用程序中的应用。
在现代的应用程序开发中,经常会涉及到在不同的层之间传输数据。例如,从客户端发送的数据需要在服务器端进行处理和验证,然后可能会传递给数据库或其他外部服务。在这个过程中,数据的结构和格式可能会有所不同,这就是DTO的用武之地。
DTO是一种用于定义数据传输的对象,它定义了传输的数据的结构和字段。通过使用DTO,我们可以明确指定在不同层之间传输的数据的内容,确保数据的一致性和有效性。DTO还可以用于数据验证,以确保传输的数据符合预期的格式和规范。
在本篇【NestJS学习日记】中,我们将学习如何创建和使用DTO。我们将了解如何定义DTO类,如何在NestJS的控制器和服务中使用DTO,并且如何进行数据验证和转换。我们还将研究DTO的最佳实践和常见的使用场景。
通过理解和掌握DTO的概念和应用,我们将能够更好地组织和管理数据传输,在不同的层之间实现松耦合和有效的数据交互。DTO是NestJS应用程序开发中的重要概念,它能够提高代码的可读性、可维护性和可扩展性。
在接下来的文章中,让我们一起深入研究DTO的概念和应用,掌握在NestJS应用程序中使用DTO的技巧和技巧!
前期准备
这里需要先安装依赖
kotlin
npm install class-validator
npm install class-transformer
npm install @nestjs/mapped-types
创建 DTO
在对应的 Module 目录下新建目录 'dto/',然后新建 dto 文件,以 cat module 为例,新建 'cat.dto.ts' 文件,然后在文件内部新增两个 dto 类。
ts
export class CreateCatDto {
name: string;
age: number;
}
export class UpdateCatDto {
name?: string;
age?: number;
}
使用 DTO
Nestjs 是使用 Typescript 进行编写的,所以我们可以将这两个 dto 为 Controller 中的方法进行参数的类型描述。
cat.controller.ts
ts
import { Controller, Body, Post, Param, Put } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto } from './dto/cat.dto';
@Controller('cat')
export class CatController {
@Post()
createCat(@Body() body: CreateCatDto) {
return body;
}
@Put(':id')
updateCat(@Param('id') id: string, @Body() body: UpdateCatDto) {
return { id, body };
}
}
使用 DTO 对参数校验
DTO 不仅仅是对参数进行类型描述,还可以对请求的参数进行类型校验,首先我们需要增加一个全局的校验 pipe。
app.module.ts
ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe()); // 新增校验 pipe
await app.listen(3000);
}
bootstrap();
接下改变一下我们的 dto, 这里需要使用到 class-validator 提供的装饰器修饰 dto 类的属性。
ts
import { IsString, IsNumber } from 'class-validator';
export class CreateCatDto {
@IsString()
name: string;
@IsNumber()
age: number;
}
此时我们尝试 post 请求:
- 不传入任何参数,返回了一个错误信息,告诉我们参数的要求。
- 传入 name 和 age,但是 age 给一个 string,此时只返回了对于 age 参数的描述。
这就是使用 dto 对参数进行校验的方法。
继承
可以看出 CreateDto 和 UpdateDto 是相似的,所以可以使用继承的方式,但是 UpdateCatDto 的属性是可选的,这就要使用 @nestjs/mapped-types 的 PartialType。
ts
import { IsString, IsNumber } from 'class-validator';
import { PartialType } from '@nestjs/mapped-types';
export class CreateCatDto {
@IsString()
name: string;
@IsNumber()
age: number;
}
export class UpdateCatDto extends PartialType(CreateCatDto) {}
此时尝试 put 请求:
- 发出 name 和 age,没有报错。
- 只发出 name,没有报错。
- 只发出 age,但是是 string,报错 age 需要是数字类型。 可以看到 UpdateCatDto 即继承了 CreateDto 的校验,但是也有自身的可选类型描述。
总结
DTO 不仅可以帮助我们进行类型描述,还可以对 body 进行校验,并且通过继承可以把类似的类型组合起来,也不会失去校验的功能。