除了内置装饰器外,nest.js也允许我们自定义装饰器进行模块化功能开发,这里我们还是以SetMetadata为例子
不要忘记装饰器的本质,装饰器就是一个函数,在通过@符号调用时会往参数列表里加入一些特定的属性
- 创建一个自定义装饰器 nest g d roles
import { SetMetadata,ExecutionContext } from '@nestjs/common'; // 方法装饰器 export const Roles = (...args: string[]) => SetMetadata('roles', args);
创建好后可以看到这个方法,调用这个方法后会执行SetMetadata函数,定义一个路由元信息。我们在上一节注册的守卫在这一节仍然有用,不能删除
- 在controller里注册
import { ReqUrl, Roles } from 'src/roles/roles.decorator'; @Controller('login') export class LoginController { constructor(private readonly loginService: LoginService) {} @Get() @Roles('admin') @UseGuards(RoleGuard) findAll() { return reqUrl; } }
守卫内容稍作修改
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Observable } from 'rxjs'; import { Reflector } from '@nestjs/core'; import { Request } from 'express'; @Injectable() export class RoleGuard implements CanActivate { constructor(private Reflector:Reflector){} canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { // 反射的属性改为roles const admin = this.Reflector.get<string[]>('roles',context.getHandler()) console.log('通过了守卫',admin) const req = context.switchToHttp().getRequest<Request>() if(admin.includes(req.query.roles as string)){ return true }else{ return false } console.log(admin) return true } }
我们也可以自行创建一个属性装饰器
import { SetMetadata,ExecutionContext } from '@nestjs/common'; // 引入createParamDecorator函数 import { createParamDecorator } from '@nestjs/common'; import { Request } from 'express'; // createParamDecorator接受一个回调函数,该回调有两个参数,第一个data是我们调用装饰器时传入的参数,第二个是ExecutionContext类 export const ReqUrl = createParamDecorator((data:string,context:ExecutionContext) => { // 获取请求信息 const req = context.switchToHttp().getRequest<Request>() console.log('自定义属性装饰器======>',data) return req.url })
在controller中使用
@Controller('login') export class LoginController { constructor(private readonly loginService: LoginService) {} @Get() @Roles('admin') @UseGuards(RoleGuard) // 使用装饰器并传入参数 findAll(@ReqUrl('哈哈哈') reqUrl) { return reqUrl; } }
以上,当我们访问localhost:3000/login时控制台就会输出'哈哈哈'并在页面上返回请求的url信息