网站LOGO
白雾茫茫丶
页面加载中
12月4日
网站LOGO 白雾茫茫丶
记录学习、生活和有趣的事
菜单
  • 热评
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    Nest.js 实战 (四):利用 Pipe 管道实现数据验证和转换
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    • 复制图片
    • 复制图片地址
    • 百度识图
    按住ctrl可打开默认菜单

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

    谢明伟 · 原创 ·
    前端开发Nest 实战 · TypeScriptNest
    共 5429 字 · 约 3 分钟 · 533
    本文最后更新于2024年07月22日,已经过了134天没有更新,若内容或图片失效,请留言反馈

    什么是管道(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. 安装依赖

      bash 代码:
      pnpm add class-validator class-transformer
    2. 新建 /pipe/validation.pipe.ts 文件:

      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);
        }
      }
    3. main.ts 中全局注册:

      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 如下:

    ts 代码:
    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、假如我们有一个查询岗位详情的接口如下:

    ts 代码:
    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 开发中不可或缺的工具。通过合理利用管道,开发者可以专注于业务逻辑的实现,而不必过多担忧底层数据处理的细节,从而加速开发周期,提高软件质量

    声明:本文由 谢明伟(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    现在已有

    3

    条评论
    我要发表评论
    1. · · 湖北-武汉
      • 等级:Lv.1
      • 角色:访客
      • 在线:很久之前
      头像
      沙发

      这个星月主题色,配合文章字体的蓝色,看不清,还得是用白天的背景

      评论
      1. · · 广东-深圳
        • 角色:博主
        • 在线:本月
        头像

        是的,部分主题颜色没有和文章字体做适配,我一般看文章也是切到无暇主题,哈哈

        评论
        1. · · 湖北-武汉
          • 等级:Lv.1
          • 角色:访客
          • 在线:很久之前
          头像

          切换了主题色,就可以了

          评论
    博客logo 白雾茫茫丶 记录学习、生活和有趣的事 51统计 百度统计
    MOEICP 萌ICP备20236860号 ICP 粤ICP备2023007649号 ICP 粤公网安备44030402006402号

    💻️ 谢明伟 昨天 17:36 在线

    🕛

    本站已运行 2 年 337 天 19 小时 37 分

    🌳

    自豪地使用 Typecho 建站,并搭配 MyLife 主题
    白雾茫茫丶. © 2022 ~ 2024.
    网站logo

    白雾茫茫丶 记录学习、生活和有趣的事