实战使用 NestJS 搭建一个 Admin 后台服务 - 03. DTO参数校验&swagger接口文档生成&swagger 接口文档导入 apifox

实战使用 NestJS 搭建一个 Admin 后台服务 - 01. 项目搭建、配置文件和路由

实战使用 NestJS 搭建一个 Admin 后台服务 - 02. typeorm 操作 mysql&基础 crud

一、DTO参数校验

  • 同样的先安装依赖
bash 复制代码
yarn add class-validator class-transformer

1、使用内置pipe 或者 自定义pipe

  • 一般使用内置管道即可,当然有自定义处理需求的也可以自定义

  • 自定义pipe, 推荐查看官网 docs.nestjs.cn/10/pipes?id...

ts 复制代码
// src/pipe/validation.pipe.ts
import {
  ArgumentMetadata,
  Injectable,
  PipeTransform,
  BadRequestException,
} from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
import { Logger } from '../utils/log4js';

@Injectable()
export class MyValidationPipe implements PipeTransform {
  async transform(value: any, { metatype }: ArgumentMetadata) {
    if (!metatype || !this.toValidate(metatype)) {
      // 如果没有传入验证规则,则不验证,直接返回数据
      return value;
    }
    // 将对象转换为 Class 来验证
    const object = plainToInstance(metatype, value);
    const errors = await validate(object);
    if (errors.length > 0) {
      const msg = Object.values(errors[0].constraints)[0]; // 只需要取第一个错误信息并返回即可
      Logger.error(`Validation failed: ${msg}`);
      throw new BadRequestException(`Validation failed: ${msg}`);
    }
    return value;
  }

  private toValidate(metatype: any): boolean {
    const types: any[] = [String, Boolean, Number, Array, Object];
    return !types.includes(metatype);
  }
}

2、修改dto

  • 修改 create-user.dto.ts 不过 CreateUserDto继承了 user.entity.ts 所以直接修改 user.entity.ts 较为方便
ts 复制代码
import { IsNotEmpty } from 'class-validator';
import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity()
export class User {
  /** 每个实体必须至少有一个主列 */
  @PrimaryGeneratedColumn()
  id: number;

  /** @CreateDateColumn 是一个特殊列,自动为实体插入日期。无需设置此列,该值将自动设置。 */
  @CreateDateColumn({
    type: 'timestamp',
    nullable: false,
    name: 'create_time',
    comment: '创建时间',
  })
  createTime: Date;

  /** @UpdateDateColumn 是一个特殊列,在每次调用实体管理器或存储库的save时,自动更新实体日期。无需设置此列,该值将自动设置。 */
  @UpdateDateColumn({
    type: 'timestamp',
    nullable: false,
    name: 'update_time',
    comment: '更新时间',
  })
  updateTime: Date;

  @IsNotEmpty({
    message: '用户名不能为空',
  })
  @Column({ unique: true, nullable: true, comment: '用户名' })
  username: string;

  @IsNotEmpty({
    message: '邮箱不能为空',
  })
  @Column({ unique: true, nullable: true, comment: '邮箱' })
  email: string;

  @IsNotEmpty({
    message: '手机号不能为空',
  })
  @Column({ unique: true, nullable: true, comment: '手机号' })
  phone: string;

  @Column({ nullable: true, comment: '头像' })
  avatar: string;

  @IsNotEmpty({
    message: '密码不能为空',
  })
  @Column({ nullable: true, comment: '密码' })
  password: string;
}

3、全局使用 or 局部使用

  • 全局使用
  • exceptionFactory 做了一定转化,如下处理后,message 返回的是字符串,且是第一个验证错误
  • new ValidationPipe() 不对exceptionFactory 处理message 返回的是所有校验错误的字符串数组
ts 复制代码
// main.ts
import { BadRequestException, ValidationPipe } from '@nestjs/common';
/** 全局绑定验证管道 或者自定义 new MyValidationPipe() */
app.useGlobalPipes(
  new ValidationPipe({
    exceptionFactory: (errors) => {
      const firstError = errors[0];
      const message =
        firstError.constraints[Object.keys(firstError.constraints)[0]];
      return new BadRequestException(message);
    },
  }),
);
  • 局部使用, 在controller 层使用 users.controller.ts
ts 复制代码
@UsePipes(new ValidationPipe()) // 或者自定义 new MyValidationPipe()
@Post()
create(@Body() createUserDto: CreateUserDto) {
  return this.usersService.create(createUserDto);
}

4、效果展示

  • exceptionFactory 未转化
  • exceptionFactory 转化

二、swagger接口文档生成

bash 复制代码
yarn add @nestjs/swagger swagger-ui-express
  • 修改main.ts
ts 复制代码
const options = new DocumentBuilder()
  .setTitle('Cats example')
  .setDescription('The cats API description')
  .setVersion('1.0')
  .addTag('cats')
  .build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('doc', app, document); // 使用doc 不使用api 做一定区分

三、导入api fox

  • apifox 自行下载
  • 可以看到已经导入了,但body内相关参数并没有
  • 接下来进行swagger 装饰器文档编写

四、编写swagger 装饰器文档

1、修改user.entity.ts

ts 复制代码
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty } from 'class-validator';
import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity()
export class User {
  /** 每个实体必须至少有一个主列 */
  @PrimaryGeneratedColumn()
  id: number;

  /** @CreateDateColumn 是一个特殊列,自动为实体插入日期。无需设置此列,该值将自动设置。 */
  @CreateDateColumn({
    type: 'timestamp',
    nullable: false,
    name: 'create_time',
    comment: '创建时间',
  })
  createTime: Date;

  /** @UpdateDateColumn 是一个特殊列,在每次调用实体管理器或存储库的save时,自动更新实体日期。无需设置此列,该值将自动设置。 */
  @UpdateDateColumn({
    type: 'timestamp',
    nullable: false,
    name: 'update_time',
    comment: '更新时间',
  })
  updateTime: Date;

  @IsNotEmpty({
    message: '用户名不能为空',
  })
  @ApiProperty({ uniqueItems: true, description: '用户名' })
  @Column({ unique: true, nullable: true, comment: '用户名' })
  username: string;

  @IsNotEmpty({
    message: '邮箱不能为空',
  })
  @ApiProperty({ uniqueItems: true, description: '邮箱' })
  @Column({ unique: true, nullable: true, comment: '邮箱' })
  email: string;

  @IsNotEmpty({
    message: '手机号不能为空',
  })
  @ApiProperty({ uniqueItems: true, description: '手机号' })
  @Column({ unique: true, nullable: true, comment: '手机号' })
  phone: string;

  @ApiProperty({ description: '头像' })
  @Column({ nullable: true, comment: '头像' })
  avatar: string;

  @IsNotEmpty({
    message: '密码不能为空',
  })
  @ApiProperty({ description: '密码' })
  @Column({ nullable: true, comment: '密码' })
  password: string;
}

2、重复 三、导入api fox

下一篇

本篇完成了参数校验的相关工作,下篇将进行jwt 的逻辑编写

相关推荐
星释1 小时前
Rust 练习册 :Leap与日期计算
开发语言·后端·rust
码事漫谈5 小时前
C++死锁深度解析:从成因到预防与避免
后端
码事漫谈5 小时前
智能体颠覆教育行业:现状、应用与未来展望调研报告
后端
蓝-萧5 小时前
【玩转全栈】----Django基本配置和介绍
java·后端
priority_key5 小时前
排序算法:堆排序、快速排序、归并排序
java·后端·算法·排序算法·归并排序·堆排序·快速排序
韩立学长5 小时前
基于Springboot的旧时月历史论坛4099k6s9(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
编程社区管理员6 小时前
React 发送短信验证码和验证码校验功能组件
前端·javascript·react.js
全马必破三6 小时前
React“组件即函数”
前端·javascript·react.js
三思而后行,慎承诺6 小时前
React 底层原理
前端·react.js·前端框架
座山雕~6 小时前
html 和css基础常用的标签和样式
前端·css·html