1. 什么是DTO
DTO(Data Transfer Object)是一种用于描述数据模型和数据传输的对象。
它是一种用于在不同层之间传输数据的设计模式。在应用程序的不同组件中,数据通常以各自不同的格式和方式存储。而使用 DTO 可以将这些不同的数据格式和方式转换成一种统一的、标准化的方式,从而方便数据的传输和共享。通过 DTO ,我们可以将数据模型和数据传输途径分开定义,提高应用程序的可扩展性、可维护性和可重用性。
在 NestJS 中,DTO 是一个精简的对象,用于捕获在应用程序的不同部分和层之间传递的数据。并且在业务逻辑和数据访问之间进行解耦。通常,我们会在控制器和服务之间传递 DTO 对象。
对于控制器而言,DTO 是用于接收 HTTP 请求数据的一种数据结构,用于将 HTTP 请求中的数据转换成应用程序需要的数据格式。从服务角度讲,DTO 是用于传递数据模型的一种数据结构,用于将服务返回的数据转换成适合客户端应用程序的格式。
因此,DTO 是 NestJS 中非常重要的概念,它可以帮助我们在应用程序中保持良好的可扩展性和可维护性。
2. 如何使用
2.1 新建一个resource login, 一个pipe login
nest g res login
nest g pi login
- 首先先看pipe如何在controller中使用
login.pipe.ts
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
@Injectable()
export class LoginPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
console.log(value, metadata);
return value;
}
}
login.controller.ts
@Post()
create(@Param(LoginPipe) createLoginDto: CreateLoginDto) {
return this.loginService.create(createLoginDto);
}
使用curl
curl -d "name=admin&password=123456" -X POST http://localhost:3000/login
- value: 对应传入的值
- type: 对应controller中post的@Body的名称
- data: 对应接受的属性
使用下面的装饰器 结果不同
@Post()
create(@Param('name', LoginPipe) createLoginDto: CreateLoginDto) {
return this.loginService.create(createLoginDto);
}
=====
@Body('name', LoginPipe) // 对应value就是admin data是name
- 手动写pipe进行dto验证
需要安装包
npm i -S class-validator
npm i -S class-transformer
create-login.dto.ts
import { IsNotEmpty, IsNumber, IsString, Length } from 'class-validator';
export class CreateLoginDto {
@IsNotEmpty()
@IsString()
@Length(5, 10, {
message: '字符在5个到10个之间',
})
name: string;
@IsNotEmpty()
@IsNumber()
age: number;
}
login.pipe.ts
import {
ArgumentMetadata,
HttpException,
HttpStatus,
Injectable,
PipeTransform,
} from '@nestjs/common';
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
/** 将前端传入的值 加入到管道中 实现验证 */
@Injectable()
export class LoginPipe implements PipeTransform {
async transform(value: any, metadata: ArgumentMetadata) {
console.log(value, metadata);
const DTO = plainToInstance(metadata.metatype, value);
console.log(DTO);
const errors = await validate(DTO);
console.log('打印***errors', errors);
if (errors.length) {
throw new HttpException(errors, HttpStatus.BAD_REQUEST);
}
return value;
}
}
login.controller.ts
import { LoginPipe } from './login.pipe';
@Controller('login')
export class LoginController {
constructor(private readonly loginService: LoginService) {}
@Post()
create(@Body(LoginPipe) createLoginDto: CreateLoginDto) {
return this.loginService.create(createLoginDto);
}
}
传输字段不符合规则 返回的errors信息
流程如下:
首先接受前端的数据,@Post的@Body使用LoginPipe,在Login.pipe.ts中就可以获取到值,使用class-transformer中的plainToInstance进行实例化,调用class-validate中的validate方法,可以获取结果是否正确,然后进行相应的返回信息。
- 使用NestJS中的全局pipe
上面自己手动配置麻烦,NestJS提供了全局的pipe验证,只需要在
main.ts
import { ValidationPipe } from '@nestjs/common';
app.useGlobalPipes(new ValidationPipe());
验证结果如下: