实战使用 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 的逻辑编写

相关推荐
GISer_Jing6 分钟前
AI驱动营销:业务技术栈实战(From AIGC,待总结)
前端·人工智能·aigc·reactjs
小马爱打代码29 分钟前
SpringBoot:封装 starter
java·spring boot·后端
STARSpace888842 分钟前
SpringBoot 整合个推推送
java·spring boot·后端·消息推送·个推
Marktowin1 小时前
玩转 ZooKeeper
后端
GIS之路2 小时前
GDAL 实现影像裁剪
前端·python·arcgis·信息可视化
AGMTI2 小时前
webSock动态注册消息回调函数功能实现
开发语言·前端·javascript
蓝眸少年CY2 小时前
(第十二篇)spring cloud之Stream消息驱动
后端·spring·spring cloud
码界奇点2 小时前
基于SpringBoot+Vue的前后端分离外卖点单系统设计与实现
vue.js·spring boot·后端·spring·毕业设计·源代码管理
不会Android的潘潘2 小时前
受限系统环境下的 WebView 能力演进:车载平台 Web 渲染异常的根因分析与优化实践
android·java·前端·aosp
建军啊2 小时前
java web常见lou洞
android·java·前端