Nest.js 实战 (四):利用 Pipe 管道实现数据验证和转换

news2024/11/13 15:15:41

什么是管道(Pipe)?

在 Nest.js 中,管道(Pipelines) 是一种强大的功能,用于预处理进入控制器方法的请求数据,如请求体、查询参数、路径参数等。管道允许开发者在数据到达控制器方法之前对数据进行转换、验证、清理或执行其他预处理任务。这使得 Nest.js 应用更加健壮、可维护和一致。

以下是 Nest.js 中管道的一些主要用途:

  • 数据转换:管道如 ParseIntPipeParseFloatPipeParseArrayPipe 等可以将原始输入数据转换为应用内部所需的类型,如将字符串转换为整数或浮点数,或将字符串表示的数组转换为数组,保证了数据的一致性和可用性
  • 数据验证:管道可以确保传入的数据符合预期的格式和规则。例如,使用 ValidationPipe 结合 class-validator,可以自动验证请求体或查询参数是否满足特定的 DTO(数据传输对象)定义,从而预防因数据格式错误引起的运行时异常
  • 错误处理:如果数据不符合管道的规则,管道可以抛出异常,从而阻止请求的进一步处理,并向客户端返回适当的错误信息
  • 一致性:管道有助于在整个应用中保持一致性,避免在不同的控制器或方法中重复相同的预处理逻辑
  • 可插拔性和重用性:管道是可插拔的组件,可以很容易地在多个控制器或方法之间共享和重用

内置管道

Nest.js 自带九个开箱即用的管道:

  • ValidationPipe:验证和转换传入的数据。它使用 class-validator 库来检查数据是否符合定义在 DTOs 或请求模型上的验证规则
  • ParseIntPipe:将字符串类型的参数转换为整数
  • ParseFloatPipe:将字符串类型的参数转换为浮点数
  • ParseBoolPipe:将字符串类型的参数转换为布尔值
  • ParseArrayPipe:将字符串形式的数组转换为数组
  • ParseUUIDPipe:解析字符串并验证是否为 UUID
  • ParseEnumPipe:将传入的值转换为枚举类型中的成员
  • DefaultValuePipe:如果传入的参数是 undefinednull,则使用默认值替换它
  • ParseFilePipe:用于处理上传的文件,它可以验证文件的类型、大小等,确保上传的文件符合预期

自定义管道

  1. 安装依赖
pnpm add class-validator class-transformer
  1. 新建 /pipe/validation.pipe.ts 文件:
import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';

@Injectable()
export class ValidationPipe implements PipeTransform {
  async transform(value: any, { metatype }: ArgumentMetadata) {
    if (!metatype || !this.toValidate(metatype)) {
      // 如果没有传入验证规则,则不验证,直接返回数据
      return value;
    }
    // 将对象转换为 Class 来验证
    const object = plainToClass(metatype, value);
    const errors = await validate(object);
    if (errors.length > 0) {
      const msg = Object.values(errors[0].constraints)[0]; // 只需要取第一个错误信息并返回即可
      // 自定义校验返回格式
      throw new BadRequestException(`参数校验失败: ${msg}`);
    }
    return value;
  }
  private toValidate(metatype: any): boolean {
    const types: any[] = [String, Boolean, Number, Array, Object];
    return !types.includes(metatype);
  }
}
  1. main.ts 中全局注册:
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@/pipe/validation.pipe'; // 全局管道

import { AppModule } from './app.module';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // 全局参数校验
  app.useGlobalPipes(new ValidationPipe());

  await app.listen(3000);
} 
bootstrap();

管道测试

1、假如我们现在有一个添加岗位的接口,它的 DTO 如下:

import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsNumber, IsOptional, IsUUID } from 'class-validator';

export class SavePostDto {
  @ApiProperty({
    type: String,
    description: '父级id',
    default: '0c01ef7d-2f6f-440a-b642-62564d41f473',
    required: false,
  })
  @IsOptional()
  @IsUUID('all', { message: 'parentId 参数不正确' })
  parentId?: string;

  @ApiProperty({
    type: String,
    description: '岗位名称',
    default: '前端工程师',
  })
  @IsNotEmpty({ message: '岗位名称必填' })
  name: string;

  @ApiProperty({
    type: String,
    description: '组织id',
    default: 'f45cd48b-e703-49db-91be-ae7f594e73e0',
  })
  @IsUUID('all', { message: 'orgId 参数不正确' })
  orgId: string;

  @ApiProperty({
    type: Number,
    description: '排序',
    default: 1,
  })
  @IsNumber(
    {},
    {
      message: '排序必须为数字',
    },
  )
  sort: number;

  @ApiProperty({
    type: String,
    description: '岗位描述',
    default:
      '前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色。从狭义上讲,前端工程师使用 HTML、CSS、JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端、移动端网页,处理视觉和交互问题。',
    required: false,
  })
  describe?: string;
}

如果我们提交的请求体中缺少了参数,它就会提示:
在这里插入图片描述

2、假如我们有一个查询岗位详情的接口如下:

import { Body, Controller, Get, ParseUUIDPipe} from '@nestjs/common';
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger'; // swagger 接口文档

import { ResponseSavePostDto } from './dto/response-post.dto';
import { PostManageService } from './post-manage.service';

@ApiTags('智能行政-岗位管理')
@Controller('post-manage')
export class PostManageController {
  constructor(private readonly postManageService: PostManageService) { }

  /**
   * @description: 查询岗位详情
   */
  @Get(':id')
  @ApiOkResponse({ type: ResponseSavePostDto })
  @ApiOperation({ summary: '查询岗位详情' })
  findOne(@Param('id', new ParseUUIDPipe()) id: string) {
    return this.postManageService.findOne(id);
  }
}

我们要保证 idUUID,我们就可以使用 ParseUUIDPipe 内置管道,如果参数不对,管道就会给出报错信息:
在这里插入图片描述

这里我们演示了自定义管道和 ParseUUIDPipe 管道的用法,其它内置管道用法也一样,大家可以根据自己的实际情况选择合适的管道。

总结

Nest.js 中的 管道(Pipelines) 不仅简化了数据处理流程,还提升了应用的健壮性和安全性,是现代 Web 开发中不可或缺的工具。通过合理利用管道,开发者可以专注于业务逻辑的实现,而不必过多担忧底层数据处理的细节,从而加速开发周期,提高软件质量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1943670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用GoAccess进行Web日志可视化

运行网站的挑战之一是了解您的 Web 服务器正在做什么。虽然各种监控应用程序可以在您的服务器以高负载或页面响应缓慢运行时提醒您,但要完全了解正在发生的事情,唯一的方法是查看 Web 日志。阅读日志数据页面并了解正在发生的事情可能需要花费大量时间。…

慎用 readFileSync 读取大文件, 教你一招如何优雅处理大文件读取

我们在编写 nodejs 服务的时候,有时候需要使用 fs.readFileSync api 去读取文件,但是使用 fs.readFileSync 会将文件读取在内存中,如果遇到了文件很大时,fs.readFileSync 会占据服务器大量的内存,即使读取的文件比较小…

代发考试战报:7月16号武汉参加HCIP-Transmission传输 H31-341考试通过

代发考试战报:7月16号武汉参加HCIP-Transmission传输 H31-341考试通过,,有2个题好像没见到过,其他都是题库里的原题,题库很准,这个题库也不是一直不变的,也没规律可循什么时候变题,哪…

【TAROT学习日记】韦特体系塔罗牌学习(6)——教皇 THE HIEROPHANT

韦特体系塔罗牌学习(6)——教皇 THE HIEROPHANT 目录 韦特体系塔罗牌学习(6)——教皇 THE HIEROPHANT牌面分析1. 基础信息2. 图片元素 正位牌意1. 关键词/句2.爱情婚姻3. 学业事业4. 人际财富5. 其他象征意 逆位牌意1. 关键词/句2…

PostgreSQL 中如何实现数据的批量插入和更新?

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!📚领书:PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何实现数据的批量插入和更新?一、批量插入数据1. 使用 INSERT INTO 语句结…

PSINS工具箱函数介绍——r2d

介绍工具箱里面r2d这个小函数的作用。 程序源码 function deg r2d(rad) % Convert angle unit from radian to degree % % Prototype: deg r2d(rad) % Input: rad - angle in radian(s) % Output: deg - angle in degree(s) % % See also r2dm, r2dms, d2r, dm2r, dms2r% …

运维锅总详解VLAN

本文介绍了VLAN作用、公司多个部门VLAN举例、VLAN间路由、VLAN协议控制字段解释及工作流程、VLAN历史演进等方面对VLAN技术进行详细分析。希望对您理解VLAN有所帮助! 一、VLAN作用 VLAN(Virtual Local Area Network,虚拟局域网)…

FreeSWITCH 1.10.10 简单图形化界面26-在网页上播放SIP设备视频

​ FreeSWITCH 1.10.10 简单图形化界面26-在网页上播放SIP设备视频 1、前言2、大概流程3、测试环境4、安装流媒体服务器5、设置流媒体服务器接口6、简单写个web接口7、测试一下1、web播放在线播放器1在线播放器2本地video控件 2、vlc播放vlc播放rtmpvlc播放rtsp 8、总结 1、前…

简过网:公务员公示后是不是就没有问题了?

A:请问,公务员录用考试公示期过后是不是说明就正式录用了? Q:公务员已经公示录用,就说明前期政审已经过关,档案在前期的审查工作中没有发现问题,在入职前,档案会调入组织部&#xf…

10.发布确认

解决消息不丢失的一个重要环节。 前面说过消息持久化,可能出现一种情况就是: 尽管它告诉rabbitmq将消息保存到磁盘,但是依然存在当消息刚准备存储到磁盘的时候,但是还没有存储完,消息还在缓存的一个间隔点。此时消息…

充电桩--交流充电桩硬件原理以及竞品方案

聚焦光伏领域、深耕储能市场、探究充电技术 微信公众号 小Q下午茶 聚焦光伏领域,深耕储能市场,探究充电技术 47篇原创内容 公众号 一、交流充电桩系统介绍 为了实现能源安全和“双碳”目标的达成,充电桩是需要智能电网支持,…

Linux 各目录

Linux 是一个非常严谨的操作系统,每个目录都有自己的作用,这些作用是固定的,没有特殊情况,应严格执行; Linux 中所有东西以文件形式存储和管理,命令也不例外; 以下四个 bin 是二进制文件&…

linux C++ onnxruntime yolov8 视频检测Demo

linux C onnxruntime yolov8 视频检测Demo 目录 项目目录 效果 ​编辑CMakeLists.txt 代码 下载 项目目录 效果 ./yolov8_demo --help ./yolov8_demo -c2 -ptrue ./yolov8_demo -c1 -strue CMakeLists.txt # cmake needs this line cmake_minimum_required(VERSION 3…

力扣最热一百题——3.最长连续序列

目录 题目链接:128. 最长连续序列 - 力扣(LeetCode) 题目描述 示例 提示 解法一:排序双指针剪枝 思路 1. 获取数组长度并进行特判 2. 对数组进行排序 3. 初始化变量 4. 遍历数组并寻找最长连续子序列 5. 返回结果 总结…

Linux笔记-对.a静态库的进一步理解(2024-04-09)

过程 问: Linux中生成.a库时候,如果代码里面调用了一些只引用未定义的函数,gcc不报错,但能生成对应的.a文件,这是为什么?再写一个执行程序去调用.a库时,链接时就会报这个.a库未定义的引用&…

列举excel中调整行高列宽的五种方法

列举excel中调整行高列宽的五种方法 在Excel中调整行高列宽的方法有以下五种: 使用鼠标手动调整行高列宽:将鼠标悬停在行或列的边界上,光标会变成双向箭头,此时按住鼠标左键并拖动边界即可调整行高或列宽。 使用快捷键调整行高列…

node和npm安装;electron、 electron-builder安装

1、node和npm安装 参考: https://blog.csdn.net/sw150811426/article/details/137147783 下载: https://nodejs.org/dist/v20.15.1/ 安装: 点击下载msi直接运行安装 安装完直接cmd打开可以,默认安装就已经添加了环境变量&…

vue3通过html2canvas dom转图片复制到剪贴板和dom转图片并下载

代码实现 <template><div class"page"><div id"to-img-dom"><strong>我是图片标题</strong><p>我是内容&#xff0c;我是内容&#xff0c;我是内容&#xff0c;我是内容&#xff0c;我是内容&#xff0c;我是内容&am…

Jupyter notebook 快速入门

1、什么是jupyter notebook Jupyter Notebook是一个交互式笔记本环境&#xff0c;可以在其中同时编写和运行代码&#xff0c;以及进行数据分析和可视化。它支持多种编程语言&#xff08;如Python、R、Julia等&#xff09;&#xff0c;并提供了丰富的功能和工具供用户使用。Jup…

如何减少网站延迟?

什么是网络延迟&#xff1f; Web 延迟描述了网站响应用户请求所花费的时间。它是网络性能的一个重要因素&#xff0c;因为它决定了用户访问网站内容并与之交互的速度。当延迟很高时&#xff0c;网站会变得缓慢且反应迟钝&#xff0c;从而导致用户不满意。延迟可能由多种因素引…