Nest实现自定义装饰器

Nest内置了大量的装饰器,且绝大部分的功能都是通过装饰器来实现的。

但是如果当现有的装饰器不满足我们的需求时,我们也可以自己开发一个装饰器,接下来我们实现一个自定义的装饰器。

首先创建一个nest项目:

js 复制代码
nest new custom-decorator -p pnpm

然后在新创建的项目中新建一个decorator文件:

js 复制代码
nest g decorator aaa --flat

图中这个装饰器就是自定义的装饰器。

之前我们使用的装饰器是@SetMetadata 然后加了个Guard,将metadata取出来做一些判断。首先新建一个Guard:

js 复制代码
nest g guard aaa --flat --no-spec

然后使用reflector来取上一步设置的metadata:

之后将这个Guard加到对应的路由上,刷新页面,就可以看到我们在guard中取到设置的metadata了:

不同的metadata有不同的业务场景,有些是用于权限,有些用于其他场景。

但现在都使用@SetMetadata来设置太原始了。

这时候可以使用自定义的decorator来封装一层: 装饰器可以简化成这样:

并且将Guard中获取metadatakey改成自定义装饰器中配置的key 然后和页面路由改为/hello,刷新页面: 这样就可以看到我们设置的metadata了。

除此之外,我们发现这样使用会在一个handler上使用多个装饰器,每次使用都要写好几个类似的。我们可以将装饰器合并起来,直接在自定义装饰器中使用applyDecorators将其他的装饰器合并起来: 我们使用applyDecorators将各个装饰器串联起来,在它内部来调用传入的装饰器。

然后我们在controller中新加一个路由,并使用这个自定义的装饰器: 根据aab装饰器中的定义,第一个参数是路由名称,第二个参数是所设置的metadata的值,打开/hello1页面,然后刷新,查看控制台打印的信息: 我们可以看到设置的值user1成功打印了出来。

此时,这三个的的效果是一样的: 这就是我们说的自定义装饰器。

此外还有自定义参数装饰器: 我们使用createParamDecorator来创建一个自定义参数的装饰器,其中createParamDecorator接收的参数中,第一个是传入的值,第二个是上下文,可以用来取出responserequest对象等。

我们先来用一下,在浏览器中输入/hello3路由,刷新页面,查看页面的信息: 我们发现页面展示的信息就是装饰器返回的内容(当然这块还会根据这个返回的参数来自定义一些内容)。

上面说过createParamDecorator的第二个参数ExecutionContext是上下文,可以取出来requestresponse等对象,所以在这个参数装饰器内部,我们可以实现内置的@Param@Query@Ip@Headers等装饰器的功能。

我们来试试通过ExecutionContext来获取请求的headers,然后通过传入的参数拿到具体的请求信息:

首先我们先定义这个自定义装饰器: 然后在controller中新增一个/hello4的路由,并在其中使用@Headers装饰器,获取Accept信息: 此时我们使用了内置的装饰器@Headers和自定义装饰器,都是来获取请求体的accept信息,在页面中输入/hello4路由,刷新页面,查看控制台打印的信息: 可以看到打印出来的信息都一样。

我们再使用ExecutionContext,自定义装饰器来实现一个@Query的功能:

首先再新建一个新的自定义装饰器: 在这里面我们通过ExecutionContext获取到了请求的request信息,返回了对应的request.query[key],之后我们在controller中新建一个路由: 然后打开浏览器输入路由/hello5?aaa=yangmy&bbb=chzuze,刷新页面,查看控制台打印内容: @Query的使用一模一样。

而且这些装饰器和内置装饰器一样,也都可以使用Pipe来做参数的转换和验证:


上面我们讲的是对方法和参数的自定义装饰器,那对class的装饰器我们改如何实现?

其实也很简单,首先我们定义一个仅用于路由功能的自定义装饰器: 然后我们替换掉controller中的@Controller: 然后我们可以看到控制台中的日志,路由已被添加了一层/aaa

再次访问页面时需要在之前的路由前面加上/aaa

同样,我们还可以使用applyDecorators组合多个装饰器给controller使用: 在这个装饰器中我们不仅给这个controller设置了前置路由,同样设置了keyeeemetadata

之后我们使用这个装饰器,并向guard中添加一条信息打印:

然后浏览器访问http://localhost:3000/aaa,查看控制台日志打印: 成功访问到了在自定义装饰器中设置的值为yangmy的metadata.

总结:

方法装饰器就是传入参数,然后调用下其他的装饰器就好,比如对@SetMetadata的封装。

如果想将多个装饰器组合成一个,就使用applyDecorators这个api。

class装饰器和方法装饰器的用法是一样的。

可以使用createParamDecorator创建参数装饰器,通过它可以拿到ExecutionContext,这样我们就可以拿到request,response,从而可以实现更多的内置装饰器功能,headers,query,ip等等

相关推荐
小桥风满袖8 分钟前
极简三分钟ES6 - ES8中字符串扩展
前端·javascript
张拭心8 分钟前
这就是流量的力量吗?用豆包 AI 编程做的xhs小组件帖子爆了
前端·ai编程·豆包marscode
少年阿闯~~12 分钟前
CSS3的新特性
前端·javascript·css3
IT_陈寒18 分钟前
React性能优化:这5个Hook技巧让我的组件渲染效率提升50%(附代码对比)
前端·人工智能·后端
Captaincc20 分钟前
9 月 20 日,TRAE Meetup@Guangzhou 相聚羊城
人工智能·后端
Brookty23 分钟前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序
智能化咨询34 分钟前
【Linux】【实战向】Linux 进程替换避坑指南:从理解 bash 阻塞等待,到亲手实现能执行 ls/cd 的 Shell
前端·chrome
Anson Jiang36 分钟前
浏览器标签页管理:使用chrome.tabs API实现新建、切换、抓取内容——Chrome插件开发从入门到精通系列教程06
开发语言·前端·javascript·chrome·ecmascript·chrome devtools·chrome插件
风象南39 分钟前
SpringBoot Jar包冲突在线检测
后端
掘金安东尼40 分钟前
黑客劫持:周下载量超20+亿的NPM包被攻击
前端·javascript·面试