实战使用 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 小时前
常见 CSS 选择器用法
前端·css·学习·html·前端开发·css选择器
衣乌安、1 小时前
【CSS】居中样式
前端·css·css3
兔老大的胡萝卜1 小时前
ppk谈JavaScript,悟透JavaScript,精通CSS高级Web,JavaScript DOM编程艺术,高性能JavaScript pdf
前端·javascript
低代码布道师1 小时前
CSS的三个重点
前端·css
耶啵奶膘2 小时前
uniapp-是否删除
linux·前端·uni-app
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
王哈哈^_^4 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*4 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue4 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang