1. 使用TypeScript装饰器实现权限验证和日志记录
- 安装依赖:确保项目中安装了
typescript
和reflect - metadata
,因为装饰器需要reflect - metadata
支持。
npm install typescript reflect - metadata --save - dev
- 配置
tsconfig.json
:在tsconfig.json
中启用装饰器相关配置:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src"
}
}
- 实现装饰器:
import { ReflectMetadata } from'reflect - metadata';
const PERMISSION_KEY = 'permission';
// 权限验证装饰器
export function requirePermission(permission: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
Reflect.defineMetadata(PERMISSION_KEY, permission, target, propertyKey);
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
// 这里模拟权限验证逻辑,从请求上下文中获取用户权限
const userPermissions = ['admin']; // 模拟用户权限列表
if (!userPermissions.includes(permission)) {
throw new Error('Permission denied');
}
return originalMethod.apply(this, args);
};
return descriptor;
};
}
- **日志记录装饰器**:
// 日志记录装饰器
export function log() {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling method ${propertyKey} with args:`, args);
const result = originalMethod.apply(this, args);
console.log(`Method ${propertyKey} returned:`, result);
return result;
};
return descriptor;
};
}
- 在API接口中使用装饰器:
class ApiController {
@log()
@requirePermission('admin')
public someApiMethod() {
return 'This is a protected API response';
}
}
const controller = new ApiController();
try {
controller.someApiMethod();
} catch (error) {
console.error(error.message);
}
2. 装饰器执行顺序和原理
- 执行顺序:装饰器从目标方法的最内层向外层执行。在上述例子中,先执行
requirePermission
装饰器,再执行log
装饰器。这是因为装饰器的应用顺序是从里到外,而实际执行是从外到里。
- 原理:
- 定义:装饰器本质上是一个函数,它可以接收三个参数:
target
(目标对象,可能是类、方法或属性),propertyKey
(属性名,如果是类装饰器则为undefined
),descriptor
(属性描述符,如果是类装饰器则为undefined
)。
- 作用:装饰器可以在不改变原有代码逻辑的基础上,为目标对象添加额外的功能。例如,权限验证装饰器可以在方法执行前检查权限,日志记录装饰器可以在方法执行前后记录日志。
- 元数据:通过
reflect - metadata
库,装饰器可以定义和读取元数据。例如,requirePermission
装饰器使用Reflect.defineMetadata
定义了权限相关的元数据,在实际权限验证逻辑中可以读取这些元数据。