by 雪隐 from https://juejin.cn/user/1433418895994094
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可联系授权
大家好,让大家久等了!这一章介绍一下管道验证与数据转换相关的内容。
我们通过http请求的数据发送服务器里面接收到的,一般是没有类型或者全是字符串类型的数据。这样我们处理业务逻辑的时候,不得不对这些数据进行一一的转换。如果项目非常庞大这种操作无疑要很大的工作量。幸好NestJS中提供了数据转换和验证支持,能够让我们更加轻松的完成这些工作。
管道
在NestJS中,管道(Pipes)是一种用于处理输入数据的机制。管道允许你对进入应用程序的数据进行转换、验证和转变。它们是NestJS中的一种重要概念,用于帮助保证输入数据的有效性和一致性。
NestJS提供了多种类型的管道,包括:
- 转换管道(Transformation Pipes):这些管道用于将输入数据转换为期望的格式。例如,你可以使用ParseIntPipe将字符串转换为整数类型。
- 验证管道(Validation Pipes):这些管道用于验证输入数据是否符合特定的规则或条件。NestJS内置了一些常用的验证器,如IsNotEmpty、IsString、IsNumber等,你也可以自定义验证器。
- 异常管道(Exception Pipes):这些管道用于处理发生的异常。你可以创建一个自定义的异常过滤器来捕获并处理抛出的异常。
- 自定义管道(Custom Pipes):你可以根据需要创建自定义管道来实现特定的逻辑。自定义管道可以用于数据转换、验证或者执行其他操作。
使用管道非常简单,你只需在处理器(Controller)或者参数的装饰器上应用管道即可。例如,你可以在一个路由处理器方法上使用管道来验证请求体
@Post()
@UsePipes(new ValidationPipe())
create(@Body() data: CreateDto) {
// 处理请求
}
在上面的示例中,ValidationPipe被应用于create方法的参数data上,它将验证请求体是否符合CreateDto定义的规则。
管道是NestJS中用于处理输入数据的强大工具,可以帮助你确保数据的有效性和一致性,同时提高代码的可维护性。
优缺点
管道在NestJS中作为数据处理的机制具有一些优点和缺点,让我们看一下它们:
优点:
- 代码重用:使用管道可以将通用的数据转换和验证逻辑封装起来,以便在应用程序的多个地方重用。这样可以减少重复的代码编写,提高代码的可维护性和可读性。
- 数据验证:管道提供了内置的验证器和自定义验证器的功能,可以帮助你验证输入数据是否符合预期的规则和约束。这样可以确保数据的有效性和一致性,减少了错误数据进入应用程序的可能性。
- 数据转换:管道还可以对输入数据进行转换和格式化,将其转换为应用程序所需的特定格式。这对于处理输入数据的一致性和可靠性非常有用,尤其是当你需要将不同数据类型进行转换时。
- 异常处理:通过异常管道,你可以捕获并处理抛出的异常。这样可以集中处理错误和异常情况,提高应用程序的可靠性,并提供更好的错误处理机制。
缺点:
- 复杂性增加:引入管道机制可能会增加一定的复杂性,特别是对于较大的应用程序或者复杂的数据处理逻辑。需要合理地设计和组织管道,以确保其可维护性和可扩展性。
- 性能开销:管道涉及对输入数据的处理和转换,这可能会带来一些性能开销。尤其是在处理大量数据或者复杂的转换逻辑时,需要考虑性能方面的影响。
- 学习曲线:理解和使用管道机制可能需要一定的学习曲线,特别是对于新手来说。需要了解不同类型的管道、如何创建和应用它们,以及如何处理错误和异常情况。
尽管存在一些缺点,但管道作为NestJS的核心特性,仍然是一个强大而有用的工具,可以帮助你处理和保护输入数据,提高应用程序的质量和可靠性。
管道验证
官方推荐了2种验证方式,我选用class-transformer,class-validator的方式,这种方式在NestJs中被支持的很好,接下来就把管道安排到项目中来
- 首先安装依赖。
pnpm i class-transformer class-validator
- 修改dto文件
让我们修改下创建用户的Dto文件。 对每一个属性添加注解,这些注解会自动进行数据转换。如果转换失败,则会进入异常的流程。
- create-user.dto.ts
import { IsString, IsIn } from 'class-validator';
export class CreateUserDto {
@IsString()
userid: string;
@IsString()
password: string;
@IsString()
username: string;
@IsIn([0, 1])
status: number;
}
main.ts中加入全局管道验证 可以自己写管道验证,这里我使用内置的验证管道,并把它注册到全局。
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
// 全局验证管道
app.useGlobalPipes(new ValidationPipe());
...
await app.listen(serverValue.port, serverValue.host);
}
bootstrap();
- 另外还有许多内置的转换验证依赖
对于一些,参数比较少的接口,不必要写成
Dto形式,可以简单的利用内置的验证管道达到同样的效果。
ValidationPipeParseIntPipeParseFloatPipeParseBoolPipeParseArrayPipeParseUUIDPipeParseEnumPipeDefaultValuePipeParseFilePipe
gossip.controller.ts
@Get('gossip/:id')
async findGossip(@Param('id', ParseIntPipe) id: number) {
return await this.gossipService.findById(id);
}
- 测试看效果
通过下面的命令运行项目,并启动vsCode的调试模式。
npm run start:debug
先请求一个错误的类型试试,这里把status改成字符串类型的1,然后请求发现抱错
在创建用户controller里面加入一个断点
用postman来请求创建用户的接口,在断点停住的地方来查看类型。可以看到status被正确的转换为数字类型。
白名单
另外很多时候,前端传给后端数据的时候,会有垃圾数据。后端在处理数据的时候会由于这些垃圾数据而导致异常的情况。所以可以设置whitelist为true,这样只有用到class-validator里面的注解的属性才能被允许传入接口。我推荐大家要设置这个属性。
// 全局验证管道
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
还是拿创建用户的接口举例:
在请求的时候增加了一个otherProp,请求的的时候查看断点上的Dto时,这个属性已经被过滤掉了。
如果您觉得这篇文章对您有帮助别忘了点赞/评论。谢谢大家🙏!