1. Egg.js 核心特性深度解析
作为一名长期使用Egg.js开发企业级应用的工程师,我深刻体会到Ajv入参校验、AOP切面编程和异步任务这三大特性在实际项目中的价值。这些特性不仅能提升代码质量,还能显著降低维护成本。下面我将结合多年实战经验,详细剖析这些特性的实现原理和最佳实践。
1.1 Ajv入参校验:构建健壮的API防护层
1.1.1 校验机制设计原理
Ajv(Another JSON Schema Validator)是目前性能最优的JSON Schema验证器之一。在Egg.js中集成Ajv进行参数校验,其底层实现采用了编译缓存机制:
- Schema预编译:在应用启动时,所有定义的Schema会被编译为验证函数并缓存
- 快速验证:运行时直接调用预编译的验证函数,避免重复解析Schema
- 错误聚合:支持收集所有验证错误而非遇到第一个错误就返回
这种设计使得Ajv在校验性能上比直接写if-else判断高出5-10倍,特别是在高频调用的API场景下优势更为明显。
1.1.2 完整校验流程实现
下面是一个完整的类型安全校验方案,包含Schema定义、类型生成和校验拦截:
typescript复制// schema/user.ts
export const UserCreateSchema = Type.Object({
username: Type.String({
minLength: 4,
maxLength: 20,
pattern: '^[a-zA-Z0-9_]+$'
}),
password: Type.String({
minLength: 8,
format: 'password'
}),
age: Type.Number({
minimum: 18,
maximum: 120
}),
tags: Type.Array(
Type.String({ maxLength: 10 }),
{ maxItems: 5 }
)
});
// types/user.d.ts
interface UserCreateType extends Static<typeof UserCreateSchema> {}
// controller/user.ts
@HTTPController('/users')
export class UserController {
@HTTPMethod({
method: 'POST',
path: '/'
})
async create(@HTTPBody() user: UserCreateType) {
// 自动校验通过后才会执行到这里
return await this.userService.create(user);
}
}
1.1.3 高级校验技巧
- 条件校验:基于其他字段值动态调整校验规则
typescript复制const OrderSchema = Type.Object({
paymentMethod: Type.Union([
Type.Literal('credit_card'),
Type.Literal('paypal')
]),
creditCardNumber: Type.Conditional(
Type.Ref('paymentMethod'),
{
is: 'credit_card',
then: Type.String({ pattern: '^[0-9]{16}$' }),
otherwise: Type.Optional(Type.Never())
}
)
});
- 自定义格式校验:
typescript复制// 在config.default.ts中配置
config.ajv = {
customOptions: {
formats: {
phone: /^1[3-9]\d{9}$/,
password: (str) => {
return /[A-Z]/.test(str) && /[a-z]/.test(str) && /[0-9]/.test(str);
}
}
}
};
- 多语言错误消息:
typescript复制config.ajv = {
locale: 'zh',
messages: {
zh: {
required: '必填字段',
format: '格式不正确'
}
}
};
1.1.4 性能优化方案
- 共享Schema:将公共字段提取为独立Schema复用
typescript复制const BaseSchema = Type.Object({
id: Type.String({ format: 'uuid' }),
createdAt: Type.String({ format: 'date-time' })
})
