做外包任务网站,php做购物网站详情页的代码,wordpress分类标签丢失,点击app图标进入网站怎么做前言
在现代Web开发中#xff0c;数据验证是必不可少的一环#xff0c;它不仅能够确保数据的准确性#xff0c;还能提高系统的安全性。在使用NestJS框架进行项目开发时#xff0c;class-validator与class-transformer这两个库为我们提供了方便的数据验证解决方案。 本文将…前言
在现代Web开发中数据验证是必不可少的一环它不仅能够确保数据的准确性还能提高系统的安全性。在使用NestJS框架进行项目开发时class-validator与class-transformer这两个库为我们提供了方便的数据验证解决方案。 本文将通过详细的步骤和实战技巧带大家掌握如何在NestJS中使用class-validator进行数据验证。通过这篇文章你将能够学会如何使用class-validator优雅的实现数据验证以及11条实战中常用的验证技巧提高项目的数据校验能力。
使用步骤
第一步安装 class-validator 和 class-transformer
要使用 class-validator需要安装两个库class-validator 和 class-transformer。 npm install class-validator class-transformer
第二步创建 DTO数据传输对象
在 NestJS 中通常使用 DTOData Transfer Object来定义请求数据的结构。首先需要创建一个用于用户注册的 DTO 类并使用 class-validator 的装饰器来定义验证规则。
// src/user/dto/create-user.dto.ts
import { IsString, IsEmail, IsNotEmpty, Length } from class-validator;export class CreateUserDto {IsString()IsNotEmpty()Length(4, 20)username: string;IsEmail()email: string;IsString()IsNotEmpty()Length(8, 40)password: string;
}在这个 DTO 中定义了三个字段username、email 和 password并使用 class-validator 的装饰器指定了验证规则。
第三步使用管道验证数据
接下来需要在控制器中使用 DTO并通过 NestJS 的管道Pipes来验证传入的数据。
// src/user/user.controller.ts
import { Controller, Post, Body } from nestjs/common;
import { CreateUserDto } from ./dto/create-user.dto;Controller(user)
export class UserController {Post(register)async register(Body() createUserDto: CreateUserDto) {// 处理注册逻辑return { message: User registered successfully, data: createUserDto };}
}在这个例子中在 register 方法中使用了 Body() 装饰器来获取请求体并传入了 CreateUserDto。NestJS 会自动验证该 DTO如果验证失败将抛出异常并返回适当的错误响应。
第四步全局启用验证管道
为了更方便地管理可以全局启用验证管道这样所有的 DTO 验证都会自动进行。
// src/main.ts
import { ValidationPipe } from nestjs/common;
import { NestFactory } from nestjs/core;
import { AppModule } from ./app.module;async function bootstrap() {const app await NestFactory.create(AppModule);app.useGlobalPipes(new ValidationPipe());await app.listen(3000);
}bootstrap();在 main.ts 文件中使用 ValidationPipe 全局启用了验证管道。这样一来无论在哪个控制器中使用 DTONestJS 都会自动进行数据验证。当然也可以仅对某些控制器开启验证管道详情参考下方实战技巧。
实战使用技巧
1. 局部验证管道
可以为特定的路由或控制器方法配置验证管道而无需全局启用。这样可以在不同的场景下灵活使用不同的验证规则。
import { Controller, Post, Body, UsePipes, ValidationPipe } from nestjs/common;
import { CreateUserDto } from ./dto/create-user.dto;Controller(user)
export class UserController {Post(register)UsePipes(new ValidationPipe({transform: true,whitelist: true,forbidNonWhitelisted: true,}))async register(Body() createUserDto: CreateUserDto) {// 处理注册逻辑return { message: User registered successfully, data: createUserDto };}
}2. 自定义错误消息
class-validator 允许为每个验证规则定义自定义错误消息。例如
import { IsString, IsNotEmpty, Length, IsEmail } from class-validator;export class CreateUserDto {IsString({ message: 用户名必须是字符串 })IsNotEmpty({ message: 用户名不能为空 })Length(4, 20, { message: 用户名长度必须在4到20个字符之间 })username: string;IsEmail({}, { message: 邮箱格式不正确 })email: string;IsString({ message: 密码必须是字符串 })IsNotEmpty({ message: 密码不能为空 })Length(8, 40, { message: 密码长度必须在8到40个字符之间 })password: string;
}3. 嵌套对象验证
如果 DTO 中包含嵌套对象可以使用 ValidateNested() 装饰器进行验证。例如
import { Type } from class-transformer;
import { ValidateNested, IsString, IsNotEmpty } from class-validator;class AddressDto {IsString()IsNotEmpty()street: string;IsString()IsNotEmpty()city: string;
}export class CreateUserDto {IsString()IsNotEmpty()username: string;ValidateNested()Type(() AddressDto)address: AddressDto;
}3. 组合验证装饰器
有时可能需要将多个验证规则组合在一起这时可以使用 ValidatorConstraint() 来创建自定义验证装饰器。例如
判断数据库中是否已经存在用户名
import { registerDecorator, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface } from class-validator;ValidatorConstraint({ async: false })
export class IsUsernameUniqueConstraint implements ValidatorConstraintInterface {validate(username: any) {// 这里可以添加验证逻辑例如查询数据库return true; // 如果验证通过返回 true}
}export function IsUsernameUnique(validationOptions?: ValidationOptions) {return function (object: Object, propertyName: string) {registerDecorator({target: object.constructor,propertyName: propertyName,options: validationOptions,constraints: [],validator: IsUsernameUniqueConstraint,});};
}// 使用自定义装饰器
export class CreateUserDto {IsUsernameUnique({ message: 用户名已存在 })username: string;
}验证密码强度
import { registerDecorator, ValidationOptions, ValidationArguments } from class-validator;
export function IsStrongPassword(validationOptions?: ValidationOptions) {return function (object: Object, propertyName: string) {registerDecorator({name: isStrongPassword,target: object.constructor,propertyName: propertyName,options: validationOptions,validator: {validate(value: any, args: ValidationArguments) {return /(?.*[a-z])(?.*[A-Z])(?.*\d)(?.*[$!%*?])[A-Za-z\d$!%*?]{8,}/.test(value);},defaultMessage(args: ValidationArguments) {return 密码必须包含大小写字母、数字和特殊字符并且至少8个字符长;},},});};
}
export class ChangePasswordDto {IsStrongPassword({ message: 密码不符合强度要求 })newPassword: string;
}条件验证 根据条件进行验证可以使用 ValidateIf 装饰器。
import { ValidateIf, IsNotEmpty, IsEmail } from class-validator;
export class UpdateUserDto {IsEmail()email: string;ValidateIf(o o.email)IsNotEmpty({ message: 新邮件地址不能为空 })newEmail: string;
}使用 Matches 进行正则表达式验证 使用 Matches 装饰器可以验证字符串是否与指定的正则表达式匹配。
import { Matches } from class-validator;
export class ChangePasswordDto {Matches(/(?.*[a-z])(?.*[A-Z])(?.*\d)(?.*[$!%*?])[A-Za-z\d$!%*?]{8,}/, { message: 密码必须包含大小写字母、数字和特殊字符并且至少8个字符长 })newPassword: string;
}全局验证选项 全局启用验证管道时可以配置全局验证选项比如剥离非白名单字段、自动转换类型等。
// src/main.ts
import { ValidationPipe } from nestjs/common;
import { NestFactory } from nestjs/core;
import { AppModule } from ./app.module;
async function bootstrap() {const app await NestFactory.create(AppModule);app.useGlobalPipes(new ValidationPipe({whitelist: true, // 剥离非白名单字段forbidNonWhitelisted: true, // 禁止非白名单字段transform: true, // 自动转换类型}));await app.listen(3000);
}
bootstrap();动态验证消息 有时可能需要根据具体的验证条件动态生成错误消息可以使用 ValidationArguments 来实现。
import { IsString, MinLength, ValidationArguments } from class-validator;export class CreateUserDto {IsString()MinLength(4, {message: (args: ValidationArguments) {return 用户名太短了至少需要 ${args.constraints[0]} 个字符;},})username: string;
}Validate 自定义验证逻辑 如果内置装饰器无法满足需求可以使用 Validate 装饰器添加自定义验证逻辑。
import { Validate, ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from class-validator;ValidatorConstraint({ name: customText, async: false })
class CustomTextConstraint implements ValidatorConstraintInterface {validate(text: string, args: ValidationArguments) {return text.startsWith(prefix_); // 任何自定义逻辑}defaultMessage(args: ValidationArguments) {return 文本 ($value) 必须以 prefix_ 开头;}
}export class CustomTextDto {Validate(CustomTextConstraint)customText: string;
}属性分组验证 通过分组可以在不同情境下验证不同的字段。比如在创建和更新时可能需要验证不同的字段。
import { IsString, IsNotEmpty } from class-validator;export class CreateUserDto {IsString()IsNotEmpty({ groups: [create] })username: string;IsString()IsNotEmpty({ groups: [create, update] })password: string;
}// 使用时指定组
import { ValidationPipe } from nestjs/common;const createUserValidationPipe new ValidationPipe({ groups: [create] });
const updateUserValidationPipe new ValidationPipe({ groups: [update] });在控制器中使用不同的管道进行验证
import { Controller, Post, Put, Body, UsePipes } from nestjs/common;
import { CreateUserDto } from ./dto/create-user.dto;
import { createUserValidationPipe, updateUserValidationPipe } from ./validation-pipes;Controller(user)
export class UserController {Post(create)UsePipes(createUserValidationPipe)async createUser(Body() createUserDto: CreateUserDto) {// 处理创建用户逻辑return { message: User created successfully, data: createUserDto };}Put(update)UsePipes(updateUserValidationPipe)async updateUser(Body() updateUserDto: CreateUserDto) {// 处理更新用户逻辑return { message: User updated successfully, data: updateUserDto };}
}仅执行部分属性验证 有时可能需要只验证对象的一部分属性可以使用 PartialType 来实现。
import { PartialType } from nestjs/mapped-types;export class UpdateUserDto extends PartialType(CreateUserDto) {}
以下是如何在控制器中使用 UpdateUserDto。
// src/user/user.controller.ts
import { Controller, Post, Put, Body, Param } from nestjs/common;
import { CreateUserDto } from ./dto/create-user.dto;
import { UpdateUserDto } from ./dto/update-user.dto;
Controller(user)
export class UserController {Post(create)async createUser(Body() createUserDto: CreateUserDto) {// 处理创建用户逻辑return { message: User created successfully, data: createUserDto };}Put(update/:id)async updateUser(Param(id) id: string, Body() updateUserDto: UpdateUserDto) {// 处理更新用户逻辑return { message: User updated successfully, data: updateUserDto };}
}在这个示例中UpdateUserDto 继承自 PartialType(CreateUserDto)这意味着 UpdateUserDto 包含 CreateUserDto 中的所有属性但这些属性都是可选的。这在更新操作中非常有用因为我们可能只想提供那些需要更新的字段而不是所有字段。
验证消息的国际化 通过使用自定义验证装饰器和消息生成函数可以实现验证消息的国际化。
import { IsString, IsNotEmpty, Length, ValidationArguments } from class-validator;
import { i18n } from i18next; // 假设在项目中使用 i18nexport class CreateUserDto {IsString()IsNotEmpty({ message: (args: ValidationArguments) i18n.t(validation.usernameRequired) })Length(4, 20, { message: (args: ValidationArguments) i18n.t(validation.usernameLength, { min: 4, max: 20 }) })username: string;
}总结
使用 class-validator 结合 NestJS可以让轻松地在应用中进行数据验证不仅提高了代码的可读性还保证了数据的准确性和安全性。通过本文的介绍和技巧大家应该大致掌握了如何在 NestJS 中使用 class-validator 进行数据验证大家都在项目中实践起来吧。